﻿Imports Commander_Wars.Spieletools
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX
''' <summary>
''' Stellt algorhytmische Berechnungen an und zieht die Einheiten des Spielers
''' </summary>
''' <remarks></remarks>
Public MustInherit Class ObjektKI
#Region "Variablen"
    ''' <summary>
    ''' Wenn wir soweit fortgeschritten sind bringen uns Infantrie Transporter auch zu Feinden.
    ''' Ansonsten nur zu Besetzungen
    ''' </summary>
    ''' <remarks></remarks>
    Enum KIModiIntern
        ''' <summary>
        ''' Die KI wird gestartet
        ''' </summary>
        ''' <remarks></remarks>
        KIStart
        ''' <summary>
        ''' Die KI wartet und schaut ob sie eine Gabe einsetzen kann
        ''' </summary>
        ''' <remarks></remarks>
        StartWarten
        ''' <summary>
        ''' Die KI greift mit ihren Gebäuden an
        ''' </summary>
        ''' <remarks></remarks>
        GebäudeAngriff
        ''' <summary>
        ''' Die KI zieht die Hölliums
        ''' </summary>
        ''' <remarks></remarks>
        HölliumZiehen
        ''' <summary>
        ''' Die KI besetzt Gebäude
        ''' </summary>
        ''' <remarks></remarks>
        Besetzen
        ''' <summary>
        ''' Die KI setzt ihre Fernwaffen ein
        ''' </summary>
        ''' <remarks></remarks>
        Fernkampf
        ''' <summary>
        ''' Die KI setzt ihre Panzer ein
        ''' </summary>
        ''' <remarks></remarks>
        Nahkampf
        ''' <summary>
        ''' Die KI zieht die Infanteristen
        ''' </summary>
        ''' <remarks></remarks>
        Infanterieziehen
        ''' <summary>
        ''' Die KI zieht ihre Panzer
        ''' </summary>
        ''' <remarks></remarks>
        Nahkampfziehen
        ''' <summary>
        ''' Die KI zieht die Fernwaffen
        ''' </summary>
        ''' <remarks></remarks>
        Fernkampfziehen
        ''' <summary>
        ''' Hier werden Truppen gezogen, die wenige Leben, Treibstoff oder Munition haben.
        ''' </summary>
        ''' <remarks></remarks>
        Rückzug
        ''' <summary>
        ''' Transporter ohne Ladung verteilen Ration
        ''' </summary>
        ''' <remarks></remarks>
        Ration
        ''' <summary>
        ''' Hier werden Einheiten vereint
        ''' </summary>
        ''' <remarks></remarks>
        Einen
        ''' <summary>
        ''' Die Einheiten werden verladen
        ''' </summary>
        ''' <remarks></remarks>
        TransporterVerladen
        ''' <summary>
        ''' Die KI zieht die Transporter
        ''' </summary>
        ''' <remarks></remarks>
        Transproterziehen
        ''' <summary>
        ''' Steuert die Einheiten, welche ohne Berechnungen aus kommen
        ''' </summary>
        ''' <remarks></remarks>
        ExternGesteuerteEinheiten
        ''' <summary>
        ''' Die KI baut neue Truppen
        ''' </summary>
        ''' <remarks></remarks>
        Bauen
        ''' <summary>
        ''' Die KI setzt ihre Gabe für das Rundenende ein.
        ''' </summary>
        ''' <remarks></remarks>
        RundenEndeGabeEinsetzen
        ''' <summary>
        ''' Die KI beeendet ihren Zug
        ''' </summary>
        ''' <remarks></remarks>
        RundenEnde
    End Enum
    Enum KIModiExtern
        'ab hier stehen Einheiten Befehle
        ''' <summary>
        ''' Wir machen nichts
        ''' </summary>
        ''' <remarks></remarks>
        Keiner
        ''' <summary>
        ''' Wir wollen mit der Einheit warten
        ''' </summary>
        ''' <remarks></remarks>
        Warten
        ''' <summary>
        ''' Die Einheit soll besetzen
        ''' </summary>
        ''' <remarks></remarks>
        Besetzen
        ''' <summary>
        ''' Die Einheit soll Angreifen
        ''' </summary>
        ''' <remarks></remarks>
        Angriff
        ''' <summary>
        ''' Die Einheit soll Ration verteilen
        ''' </summary>
        ''' <remarks></remarks>
        Ration
        ''' <summary>
        ''' Die Einheit soll als Fracht aufgenommen werden
        ''' </summary>
        ''' <remarks></remarks>
        Fracht
        ''' <summary>
        ''' Die KI will zwei Einheiten einen
        ''' </summary>
        ''' <remarks></remarks>
        Einen
        ''' <summary>
        ''' Die KI repariert eine andere Einheit
        ''' </summary>
        ''' <remarks></remarks>
        Reparieren
        ''' <summary>
        ''' Die Einheit tarnt sich.
        ''' </summary>
        ''' <remarks></remarks>
        Tarnen
        ''' <summary>
        ''' Die Einheit taucht auf.
        ''' </summary>
        ''' <remarks></remarks>
        Auftauchen
        ''' <summary>
        ''' Eine S-Bombe explodiert
        ''' </summary>
        ''' <remarks></remarks>
        Explosion
        ''' <summary>
        ''' Feuert ein Silo auf ein Ziel ab.
        ''' </summary>
        ''' <remarks></remarks>
        SiloZünden
        ''' <summary>
        ''' Entlädt die Einheit auf ein Feld. 
        ''' AngreiferSchaden ist die wie vielte Einheit entladen wird.
        ''' </summary>
        ''' <remarks></remarks>
        Entladen
        ''' <summary>
        ''' Baut ein Gebäude
        ''' </summary>
        ''' <remarks></remarks>
        GebäudeBauen
        ''' <summary>
        ''' Schickt die Einheit auf die andere Schlacht
        ''' </summary>
        ''' <remarks></remarks>
        EinheitSchicken
        ''' <summary>
        ''' Baut eine Einheit in einem Flugzeugträger
        ''' </summary>
        ''' <remarks></remarks>
        FlugzeugträgerBau
        ''' <summary>
        ''' Baut eine Temporäre Basis
        ''' </summary>
        ''' <remarks></remarks>
        TemporäreBasisbauen
        ''' <summary>
        ''' Lässt eine Einheit eine Leuchtrakete Abfeuern
        ''' </summary>
        ''' <remarks></remarks>
        Leuchtrakete
        ''' <summary>
        ''' Macht die Einheit zur KO Einheit
        ''' </summary>
        ''' <remarks></remarks>
        CreateKOEinheit
        'ab hier stehen Gebäude befehle
        ''' <summary>
        ''' Sorgt dafür das diese Einheit gebaut wird.
        ''' </summary>
        ''' <remarks></remarks>
        EinheitBauen
        ''' <summary>
        ''' Lässt ein Gebäude feuern Opfer ist dabei unser Ziel.
        ''' </summary>
        ''' <remarks></remarks>
        Schuss
        ''' <summary>
        ''' Baut eine Einheit mit der Fabrik.
        ''' </summary>
        ''' <remarks></remarks>
        FabrikBauen
        ''' <summary>
        ''' Startet die Omega-Rakete auf ein Ziel
        ''' </summary>
        ''' <remarks></remarks>
        OmegaRaketeStarten
        ''' <summary>
        ''' Kauft eine erweiterug der OmegaRakete
        ''' </summary>
        ''' <remarks></remarks>
        OmegaUpgradeKaufen
        'ab hier stehen Sonstige Befehle
        ''' <summary>
        ''' Beendet die Runde der KO bleibt am Zug
        ''' </summary>
        ''' <remarks></remarks>
        RundenEnde
        ''' <summary>
        ''' Beendet die Runde der KO wechselt evtl. Nochmaliges Ziehen durch Doppelgabe..
        ''' </summary>
        ''' <remarks></remarks>
        Wechsel
        ''' <summary>
        ''' Setzt die Gabe ein
        ''' </summary>
        ''' <remarks></remarks>
        GabeEinsetzen
        ''' <summary>
        ''' Setzt die Spezialgabe ein.
        ''' </summary>
        ''' <remarks></remarks>
        SpezialgabeEinsetzen
        ''' <summary>
        ''' Setzt die Doppelgabe ein
        ''' </summary>
        ''' <remarks></remarks>
        DoppelGabeEinsetzen
        ''' <summary>
        ''' Wir wollen das Schlachtfeld wechseln
        ''' </summary>
        ''' <remarks></remarks>
        Schlachtwechseln

        ''' <summary>
        ''' Wir wollen das Wetter verändern. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        WetterWechsel
        ''' <summary>
        ''' Bewegt eine Wolke in der Luftschlacht. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        WolkeBewegen
        ''' <summary>
        ''' Verbessert eine Einheit. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        EinheitVerbessern
        ''' <summary>
        ''' Setzt den Treibstoff einer Einheit. Nur KI Passiv Befehl.
        ''' </summary>
        ''' <remarks></remarks>
        EinheitTreibstoffSetzen
        ''' <summary>
        ''' Lässt einen Vulkan Feuern. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        VulkanFeuer
    End Enum
    Enum Besetzungsprioritäten
        Keine
        FlughafebBasisHafenLaborHQStadt
        MeisteEinheiten
    End Enum
    Enum BeschussArten
        FernkampfFeindBoden
        NahkampfFeindBoden
        Geschützfeind
        eigeneFernkampf
        eigeneNahkampf
        HeilungEigene
        FernkampfFeindLuft
        NahkampfFeindLuft
    End Enum
    Enum GeldTPAngriffsModus
        NurGeld
        NurTP
        Beides
    End Enum
    Enum GebäudeSortierKriterien
        Zufall
        ''' <summary>
        ''' Wir sortieren die Gebäude nach ihrer Entfernung zum Feind.
        ''' </summary>
        ''' <remarks></remarks>
        NähestenZumFeind
    End Enum
    Enum EinheitenSortierKriterien
        Zufall
        GrößterBewegungsradius
        Preis
        KleinsterBewegungsradius
    End Enum
    ''' <summary>
    ''' Gibt an wie die KI berechnet welche Einheiten lohnende Opfer sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected OpferBerechnung As GeldTPAngriffsModus
    ''' <summary>
    ''' Führt die Schleife aus.
    ''' </summary>
    ''' <remarks></remarks>
    Public KIThreat As Threading.Thread
    '''<summary>
    ''' Alle Einheiten die dieser Spieler kontrolliert
    ''' </summary>
    ''' <remarks></remarks>
    Protected Einheiten() As ObjektEinheit = {}
    ''' <summary>
    ''' Stellt das Spielfeld dar und zeigt an welche Landschaften der Spieler sehen kann
    ''' </summary>
    ''' <remarks></remarks>
    Public Sichtfeld(,) As Boolean = {}
    ''' <summary>
    ''' Stellt alle Gebäude die dieser Spieler zu beginn der Runde beseitzt dar.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Gebäude() As ObjektGebäude = {}
    ''' <summary>
    ''' Der Spieler für den die KI zieht
    ''' </summary>
    ''' <remarks></remarks>
    Public Spieler As ObjektSpieler
    ''' <summary>
    ''' Der Modus in dem sich die Einheit die Gezogen wird befindet
    ''' </summary>
    ''' <remarks></remarks>
    Public KIModusEinheitenBefehl As KIModiExtern = KIModiExtern.Keiner
    ''' <summary>
    ''' Der Mouds in dem sich die KI im Moment befindet
    ''' </summary>
    ''' <remarks></remarks>
    Public KIModusIntern As KIModiIntern = KIModiIntern.StartWarten
    ''' <summary>
    ''' Nach welchem System Gebäude besetzt werden
    ''' </summary>
    ''' <remarks></remarks>
    Protected Besetzngspriorität As Besetzungsprioritäten
    Private Glücksfaktore As Single = 0.0
    ''' <summary>
    ''' Anhand dieses Faktors berechnet die KI den durchschnittlichen Glückswert beim Angriff
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Glücksfaktor() As Single
        Get
            Return Glücksfaktore
        End Get
        Set(ByVal value As Single)
            If value > 1 Then
                value = 1
            ElseIf value < -1 Then
                value = -1
            End If
            Glücksfaktore = value
        End Set
    End Property
    ''' <summary>
    ''' Wie oft wir bereits gebaut haben.
    ''' </summary>
    ''' <remarks></remarks>
    Protected AnzahldesBauens As Integer = 0
    ''' <summary>
    ''' Der Geldschaden den die Einheit bei einem Angriff mindestens verursachen muss gehört zu den Startwerten
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimalerGeldschaden As Single = 0
    ''' <summary>
    ''' Die Einheit die die KI zieht
    ''' </summary>
    ''' <remarks></remarks>
    Protected AktuelleEinheit As ObjektEinheit = Nothing
    ''' <summary>
    ''' Das Ziel der momentanen Einheit.
    ''' </summary>
    ''' <remarks></remarks>
    Protected AktuelleZiel As Point
    ''' <summary>
    ''' Das momentane Ziel einer Einheit
    ''' </summary>
    ''' <remarks></remarks>
    Protected Opfer As ObjektEinheit = Nothing
    ''' <summary>
    ''' Das Gebäude auf dem die Einheit gebaut wird.
    ''' </summary>
    ''' <remarks></remarks>
    Protected BauGebäude As ObjektGebäude
    ''' <summary>
    ''' Dies sagt der KI wie lange sie warten soll
    ''' </summary>
    ''' <remarks></remarks>
    Public MaxKIWarteFrame = 12
    ''' <summary>
    ''' Sagt der KI das sie warten soll
    ''' </summary>
    ''' <remarks></remarks>
    Public KIZieht As Boolean = False
    Public KIWarteFrames As Integer
    Public Property KIWarteFrame() As Integer
        Get
            Return KIWarteFrames
        End Get
        Set(ByVal value As Integer)
            KIWarteFrames += 1
            If KIWarteFrames >= MaxKIWarteFrame Then
                KIWarteFrames = 0
                KIZieht = False
            End If
        End Set
    End Property
    ''' <summary>
    ''' Gibt an wie viel mehr Wert eigene Einheiten im Vergleich zu feindlichen sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected EigenerEinheitenWert As Single = 1
    ''' <summary>
    ''' Gibt an welche Felder beschoßen werden und von wem (nicht wie viele)
    ''' 0=Fernkampf Feind Boden
    ''' 1=Nahkampf Feind Boden
    ''' 2=Geschützfeind
    ''' 3=eigene Fernkampf
    ''' 4=eigene Nahkampf
    ''' 5=Heilung Eigene
    ''' 6=Fernkampf Feind Luft
    ''' 7=Nahkampf Feind Luft
    ''' </summary>
    ''' <remarks></remarks>
    Protected Beschußfelder(,) As Byte = {}
    Public Function IsZielFernkampfBoden(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(0)
    End Function
    Public Function IsZielFernkampfLuft(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(6)
    End Function
    Public Function IsZielNahkampfBoden(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(1)
    End Function
    Public Function IsZielNahkampfLuft(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(7)
    End Function
    Public Function IsZielGeschütz(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(2)
    End Function
    Public Function IsDeckungFernkampf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(3)
    End Function
    Public Function IsDeckungNahkampf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(4)
    End Function
    Public Function IsDeckungHeilung(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(5)
    End Function
    Public Function IsFernZielFürEinheit(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.IsFlyingUnit Then
            Return IsZielFernkampfLuft(X, Y)
        Else
            Return IsZielFernkampfBoden(X, Y)
        End If
    End Function

    ''' <summary>
    ''' Die Einheit bei der wir gerade im Einheitenarray sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected MomentaneEinheit As Integer = 0
    ''' <summary>
    ''' wenn True beendet die KI ihren Zug in dem sie die KO's wechselt.
    ''' </summary>
    ''' <remarks></remarks>
    Protected RundenEndeMitWechsel As Boolean = False
    Structure Point2
        Public Sub New(ByVal P1 As Point, ByVal P2 As Point)
            Me.p1 = P1
            Me.p2 = P2
        End Sub
        Private p1 As Point
        Public Property Point1() As Point
            Get
                Return p1
            End Get
            Set(ByVal value As Point)
                p1 = value
            End Set
        End Property
        Private p2 As Point
        Public Property Point2() As Point
            Get
                Return p2
            End Get
            Set(ByVal value As Point)
                p2 = value
            End Set
        End Property
    End Structure
    ''' <summary>
    ''' Der Schaden den wir nehmen nur für NetzwerkKI
    ''' </summary>
    ''' <remarks></remarks>
    Protected AngreiferSchaden As Single
    ''' <summary>
    ''' Der Schaden den der Gegner nimmt nur für NetzwerkKI
    ''' </summary>
    ''' <remarks></remarks>
    Protected VerteidigerSchaden As Single
    ''' <summary>
    ''' So viel Schaden mehr müssen wir machen bei einem Nahkampf für ein lohnenden Angriff
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimaleTPDifferenz As Single = 0
    ''' <summary>
    ''' Der Prozentuale Anteil, den eine Einheit an Treibstoff haben darf damit sie sich nicht zurück zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Public MinimalerTreibstoff As Single = 0
    ''' <summary>
    ''' Das minmale Leben einer Einheit  damit sie sich nicht zurück zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimaleKP As Integer = 0
    ''' <summary>
    ''' Der Prozentuale Anteil, den eine Einheit an Munition haben darf damit sie sich nicht zurück zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Public MinimaleMunition As Single = 0

    Public Shared Schlachtfeld As Integer = 0
#End Region
#Region "Start"
    ''' <summary>
    ''' Startet die KI und setzt ihre Startwerte fest
    ''' </summary>
    ''' <param name="neuSpieler"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal neuSpieler As ObjektSpieler, ByVal MinimalerGeldschaden As Single, ByVal EigenerEinheitenWert As Single, ByVal Glücksfaktor As Single, ByVal Besetzungsprioriät As Besetzungsprioritäten, ByVal LohnendeOpfer As GeldTPAngriffsModus, ByVal MinimaleTPDifferenz As Single, ByVal MinimalerTreibstoff As Single, ByVal MinimaleKP As Integer, ByVal MinimaleMunition As Single)
        ObjektMaus.Visible = False
        Spieler = neuSpieler
        ReDim Sichtfeld(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Höhe - 1)
        ReDim Beschußfelder(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Höhe - 1)
        Me.MinimalerGeldschaden = MinimalerGeldschaden
        Me.EigenerEinheitenWert = EigenerEinheitenWert
        Me.Glücksfaktor = Glücksfaktor
        Me.Besetzngspriorität = Besetzungsprioriät
        Me.MinimaleTPDifferenz = MinimaleTPDifferenz
        Me.MinimaleMunition = MinimaleMunition
        Me.MinimaleKP = MinimaleKP
        Me.MinimalerTreibstoff = MinimalerTreibstoff
        OpferBerechnung = LohnendeOpfer
        'Je nach KI werden einige Variablen anders Definiert
        'Die KI überprüft die Rahmen bedingungen
        KIModusIntern = KIModiIntern.KIStart
        'Dies sind Standart initialisierungen die jede KI braucht
        Schlachtfeld = 0
        GetAllBuildings()
        CreateSicht()
        GetBeschußfelder()
    End Sub
    ''' <summary>
    ''' Ok! Wir haben Einheiten mit einer Fabrik gebaut und wollen die natürlich auch ziehen.
    ''' Sie müssen also geladen werden.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub NeueEinheitenerstellt(ByVal Sortieren As EinheitenSortierKriterien)
        GetAllUnits(Sortieren)
        CreateSicht()
    End Sub
    ''' <summary>
    ''' Fügt alle nicht gezogenen Einheiten dem Einheitenarray hinzu
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetAllUnits(ByVal Sortieren As EinheitenSortierKriterien)
        Array.Resize(Einheiten, 0)
        Dim E As New Stack(Of ObjektEinheit)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                    If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Spieler = Spieler.Spieler Then
                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).HatsichBewegt = False Then
                            E.Push(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld))
                        End If
                    End If
                End If
            Next
        Next
        Einheiten = E.ToArray
        Einheiten = SortUnits(Einheiten, Sortieren)
    End Sub
    Protected Function SortUnits(ByVal Units As ObjektEinheit(), ByVal Sortieren As EinheitenSortierKriterien) As ObjektEinheit()
        Select Case Sortieren
            Case EinheitenSortierKriterien.Zufall
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim I2 As Integer = Zufallszahl(0, Units.Length - I - 1)
                    Units2(I) = Units(I2)
                    Units(I2) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.GrößterBewegungsradius
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim MaxMovementRange As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).GetMovementRange
                        If MoveRange > MaxMovementRange Then
                            E = I2
                            MaxMovementRange = MoveRange
                        ElseIf MoveRange = MaxMovementRange And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.Preis
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim Preis As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).Kosten
                        If MoveRange > Preis Then
                            E = I2
                            Preis = MoveRange
                        ElseIf MoveRange = Preis And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            Preis = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.KleinsterBewegungsradius
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim MaxMovementRange As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).GetMovementRange
                        If MoveRange < MaxMovementRange Or MaxMovementRange < 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        ElseIf MoveRange = MaxMovementRange And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case Else
                Return Units
        End Select
    End Function
    ''' <summary>
    ''' Fügt alle Gebäude der KI dir ihr momentan gehören dem Array hinzu.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetAllBuildings()
        Array.Resize(Gebäude, 0)
        Dim G As New Stack(Of ObjektGebäude)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                If IsNothing(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude) = False Then
                    If Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude.Spieler = Spieler.Spieler Then
                        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude.GetRealGebäudeID = "VERWEIS" Then
                            Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude.CanMoveAfterBuilding = New List(Of ObjektGebäude.Variable)
                            G.Push(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude)
                        End If
                    Else
                        Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude.CanMoveAfterBuilding = Nothing
                    End If
                End If
            Next
        Next
        Gebäude = G.ToArray
    End Sub
    Public Function SortGebäude(ByVal G() As ObjektGebäude, ByVal Sortieren As GebäudeSortierKriterien) As ObjektGebäude()
        Select Case Sortieren
            Case GebäudeSortierKriterien.Zufall
                Dim G2 As New Stack(Of ObjektGebäude)
                For I = 0 To G.Length - 1
                    Dim I2 As Integer = Zufallszahl(0, G.Length - I - 1)
                    G2.Push(G(I2))
                    G(I2) = G(G.Length - I - 1)
                Next
                Return G2.ToArray
            Case GebäudeSortierKriterien.NähestenZumFeind
                Dim Entfernungen(G.Length - 1) As Integer
                For I = 0 To G.Length - 1
                    Dim E As ObjektEinheit = Nothing
                    If TypeOf G(I) Is GebäudeBasis Then
                        E = New EinheitFlak(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                    ElseIf TypeOf G(I) Is GebäudeFlughafen Then
                        E = New EinheitTarnkappenbomber(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                    ElseIf TypeOf G(I) Is GebäudeHafen Then
                        E = New EinheitTriton(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                    ElseIf TypeOf G(I) Is GebäudeLabor Then
                        E = New EinheitMech(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                    ElseIf TypeOf G(I) Is GebäudeStadt And G(I).GetBaulisteThisPlayer.Length > 0 Then
                        E = New EinheitFlak(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                    End If
                    If E Is Nothing Then
                        Entfernungen(I) = -1
                    Else
                        Dim WSS As New Wegsuchsystem(E, E.X, E.Y, Objektverwalter.Spielfeld.MomentaneSchlacht, -1, False)
                        Entfernungen(I) = WSS.Wegsuchen(True, False)
                    End If
                Next
                Dim G2(G.Length - 1) As ObjektGebäude
                For I = 0 To G2.Length - 1
                    Dim MaxMovementRange As Integer = Objektverwalter.Spielfeld.Breite * Objektverwalter.Spielfeld.Höhe
                    Dim GebäudeStelle As Integer = 0
                    For I2 = 0 To G.Length - I - 1
                        If Entfernungen(I2) < MaxMovementRange And Entfernungen(I2) >= 0 Then
                            GebäudeStelle = I2
                            MaxMovementRange = Entfernungen(I2)
                        ElseIf Entfernungen(I2) = MaxMovementRange And Entfernungen(I2) >= 0 And Zufallszahl(0, 1) = 0 Then
                            GebäudeStelle = I2
                            MaxMovementRange = Entfernungen(I2)
                        End If
                    Next
                    G2(I) = G(GebäudeStelle)
                    Entfernungen(GebäudeStelle) = Entfernungen(Entfernungen.Length - I - 1)
                    G(GebäudeStelle) = G(G.Length - I - 1)
                Next
                Return G2
            Case Else
                Return G
        End Select
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Infanteristen die dieser Spieler kontrolliert zurück
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CountInfanteristen() As Integer
        Dim Infanteristen As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Spieler.Spieler Then
                            If E.KannBesetzen = True Then
                                If E.Leben > 0 Then
                                    Infanteristen += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Infanteristen
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Einheiten von einem bestimmten Typ zurück.
    ''' </summary>
    ''' <param name="EinheitenID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CountAnyUnit(ByVal EinheitenID As String) As Integer
        Dim Units As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Spieler.Spieler Then
                            If E.Leben > 0 Then
                                If EinheitenID = E.EinheitenID Then
                                    Units += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Gibt alle Gebäude einer Art zurück
    ''' </summary>
    ''' <param name="GebäudeID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildings(ByVal GebäudeID As String) As ObjektGebäude()
        Dim IDGebäude As New Stack(Of ObjektGebäude)
        For Each Besetzung In Gebäude
            If Besetzung.GebäudeID = GebäudeID Then
                IDGebäude.Push(Besetzung)
            End If
        Next
        Return IDGebäude.ToArray
    End Function
    ''' <summary>
    ''' Zählt die Anzahl der Einheiten die noch Leben
    ''' </summary>
    ''' <remarks></remarks>
    Protected Function CountUnits() As Integer
        Dim Units As Integer = 0
        For I = 0 To Einheiten.Length - 1
            If IsNothing(Einheiten(I)) = False Then
                If Einheiten(I).Leben > 0 Then
                    Units += 1
                End If
            End If
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Gibt alle Einheiten die gebaut werden können
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllBuildUnits(ByVal Bauliste() As String, ByVal X As Integer, ByVal Y As Integer) As Integer()
        Dim EinheitenIDs As New Stack(Of Integer)
        For I = 0 To Bauliste.Length - 1
            If ObjektLadeklasse.GetEinheitenkosten(Bauliste(I)) * Spieler.Teurungsrate(Bauliste(I), X, Y) <= Spieler.Fonds Then
                If Spieler.Bauliste Is Nothing Then
                    EinheitenIDs.Push(I)
                ElseIf Spieler.Bauliste.GetWert(Bauliste(I)) >= 0 Then
                    EinheitenIDs.Push(I)
                End If
            End If
        Next
        Return EinheitenIDs.ToArray
    End Function
    ''' <summary>
    ''' Führt je nach KI Art und Zugfortschritt eine andere Untertine auf und führt sie aus
    ''' </summary>
    ''' <remarks></remarks>
    Public MustOverride Sub KISchleife()
    Private FailedRestartingThread As Boolean = False
    Public Schleife As Boolean = False
    ''' <summary>
    ''' Führt den Frame der KI aus
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub KIFrame()
        'Wir dürfen nur arbeiten wenn der Bild Backbuffer leer ist und alle Animationen abgespielt wurden.
        If BackbufferSpiel.GetBufferLength = 0 Then
            If Objektverwalter.Spielfeld.Animationen.Length = 0 Then
                If Schleife = False Then
                    If KIZieht = True Then
                        KIWarteFrame = 1
                        If KIZieht = False Then
                            WackUPThread()
                        End If
                    ElseIf FailedRestartingThread = True Then
                        WackUPThread()
                    End If
                ElseIf RundenEndeMitWechsel = False Then
                    'Die KI ist fertig dann beendet sie ihren Zug
                    KIThreat.Abort()
                    KIThreat = Nothing

                    If Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe <> ObjektSpieler.KIStufen.Passiv Then
                        Dim Befehl As KIPassivNetzwerk.Befehl
                        Befehl.Befehl = ObjektKI.KIModiExtern.RundenEnde
                        Befehl.KooX = -1
                        Befehl.KooY = -1
                        Befehl.WegX = New Integer() {-1}
                        Befehl.WegY = New Integer() {-1}
                        Befehl.OpferX = -1
                        Befehl.OpferY = -1
                        Befehl.AngreiferSchaden = -1
                        Befehl.Verteidigerschaden = -1
                        Befehl.Spieler = Objektverwalter.Spielfeld.AktuellerSpieler.Spieler
                        Hauptmenü.NetzBefehlSenden(Befehl)
                    End If

                    Objektverwalter.Spielfeld.RundenEnde()
                End If
            End If
        End If
    End Sub
    ''' <summary>
    ''' Lässt den KIThread wieder arbeiten, wenn er bereit dazu ist.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub WackUPThread()
        FailedRestartingThread = True
        'Die KI zieht nur wenn keine KO's sprechen
        Dim M As ObjektSpielMenü = Objektverwalter.Menü
        If KIThreat.ThreadState = Threading.ThreadState.WaitSleepJoin Then
            If Objektverwalter.Spielfeld.Animationen.Length = 0 Then
                If BackbufferSpiel.GetBufferLength = 0 Then
                    If Not M.Spielmodus = ObjektSpielMenü.Spielmodi.KOSprechen Then
                        If KIModusEinheitenBefehl = KIModiExtern.Keiner Then
                            If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                'Wir haben keine Einheit ausgewählt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Not Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                KIThreat.Interrupt()
                            ElseIf Not Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing Then
                                Select Case KIModusIntern
                                    Case KIModiIntern.Transproterziehen
                                        KIThreat.Interrupt()
                                End Select
                            End If
                        Else
                            If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing Then
                                'Wir haben keine Einheit ausgewählt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                'Wir haben keine Einheit ausgewählt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Objektverwalter.Spielfeld.Angriff Is Nothing And Not Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                If Objektverwalter.Spielfeld.Laufen.Zielerreicht = True Then
                                    'Wir haben keine Einheit ausgewählt und machen auch sonst keine Aktion.
                                    KIThreat.Interrupt()
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End Sub
    ''' <summary>
    ''' Startet einen neuen KIThreat
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub StartNeuerKIThreat()
        If IsNothing(KIThreat) Then
            KIThreat = New Threading.Thread(AddressOf KISchleife)
            'wir lassen so das Spiel flüssiger erscheinen
            KIThreat.Priority = Threading.ThreadPriority.Lowest
            KIThreat.Name = "KI Threat"
            KIThreat.Priority = Threading.ThreadPriority.Highest
            KIThreat.Start()
        Else
            If KIThreat.ThreadState = Threading.ThreadState.Stopped Then
                If IsNothing(KIThreat) = False Then
                    KIThreat.Abort()
                End If
                KIThreat = New Threading.Thread(AddressOf KISchleife)
                KIThreat.Name = "KI Threat"
                KIThreat.Priority = Threading.ThreadPriority.Highest
                KIThreat.Start()
            End If
        End If

    End Sub
    ''' <summary>
    ''' Macht ein komplett Update für das Spielfeld, welche Felder angegriffen werden können oder Beschießbar sind
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetBeschußfelder()
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim Einheit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not Einheit Is Nothing Then
                    'Auf dem Feld ist eine Einheit.
                    If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).Team <> Spieler.Team Then
                        Dim Nahkampffelder As Point2() = GetAllNahKampffelder(Einheit, False)
                        If Einheit.CanAttackGroundUnits Then
                            For Each Feld In Nahkampffelder
                                SetBoolean(1, True, Beschußfelder(Feld.Point2.X, Feld.Point2.Y))
                            Next
                        End If
                        If Einheit.CanAttackAirUnits Then
                            For Each Feld In Nahkampffelder
                                SetBoolean(6, True, Beschußfelder(Feld.Point2.X, Feld.Point2.Y))
                            Next
                        End If
                        Dim FernkampfFelder As Point() = GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, False)
                        If Einheit.CanAttackGroundUnits Then
                            For Each Feld In FernkampfFelder
                                SetBoolean(0, True, Beschußfelder(Feld.X, Feld.Y))
                            Next
                        End If
                        If Einheit.CanAttackAirUnits Then
                            For Each Feld In FernkampfFelder
                                SetBoolean(7, True, Beschußfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    ElseIf Einheit.Spieler = Spieler.Spieler Then
                        Dim Nahkampffelder As Point2() = GetAllNahKampffelder(Einheit, False)
                        For Each Feld In Nahkampffelder
                            SetBoolean(4, True, Beschußfelder(Feld.Point2.X, Feld.Point2.Y))
                        Next
                        Dim FernkampfFelder As Point() = GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, False)
                        For Each Feld In FernkampfFelder
                            SetBoolean(3, True, Beschußfelder(Feld.X, Feld.Y))
                        Next
                    End If
                End If
                Dim Gebäude As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude
                If Not Gebäude Is Nothing Then
                    'Auf dem Feld ist eine Einheit.
                    If Gebäude.Spieler = Spieler.Spieler Then
                        If Gebäude.Schaden < 0 Then
                            Dim Felder As Point() = Gebäude.GetAngriffsFelder
                            For Each Feld In Felder
                                SetBoolean(5, True, Beschußfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    ElseIf Not Objektverwalter.Spielfeld.Spieler(Gebäude.Spieler).Team = Spieler.Team Then
                        If Gebäude.Schaden > 0 Then
                            Dim Felder As Point() = Gebäude.GetAngriffsFelder
                            For Each Feld In Felder
                                SetBoolean(2, True, Beschußfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Stellt ein Byte als Boolean dar.
    ''' </summary>
    ''' <param name="B"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBoolean(ByVal B As Byte) As Boolean()
        Dim Bo() As Boolean = {False, False, False, False, False, False, False, False}
        If B - 128 >= 0 Then
            Bo(0) = True
            B -= 128
        End If
        If B - 64 >= 0 Then
            Bo(1) = True
            B -= 64
        End If
        If B - 32 >= 0 Then
            Bo(2) = True
            B -= 32
        End If
        If B - 16 >= 0 Then
            Bo(3) = True
            B -= 16
        End If
        If B - 8 >= 0 Then
            Bo(4) = True
            B -= 8
        End If
        If B - 4 >= 0 Then
            Bo(5) = True
            B -= 4
        End If
        If B - 2 >= 0 Then
            Bo(6) = True
            B -= 2
        End If
        If B - 1 >= 0 Then
            Bo(7) = True
            B -= 1
        End If
        Return Bo
    End Function
    ''' <summary>
    ''' Verändert ein Bit eines bytes auf den Wert 1 bzw. 0
    ''' </summary>
    ''' <param name="Ort"></param>
    ''' <param name="Wert"></param>
    ''' <param name="B"></param>
    ''' <remarks></remarks>
    Protected Sub SetBoolean(ByVal Ort As Integer, ByVal Wert As Boolean, ByRef B As Byte)
        Dim Bo() As Boolean = GetBoolean(B)
        Select Case Ort
            Case 0
                If Bo(0) = True And Wert = False Then
                    B -= 128
                ElseIf Bo(0) = False And Wert = True Then
                    B += 128
                End If
            Case 1
                If Bo(1) = True And Wert = False Then
                    B -= 64
                ElseIf Bo(1) = False And Wert = True Then
                    B += 64
                End If
            Case 2
                If Bo(2) = True And Wert = False Then
                    B -= 32
                ElseIf Bo(2) = False And Wert = True Then
                    B += 32
                End If
            Case 3
                If Bo(3) = True And Wert = False Then
                    B -= 16
                ElseIf Bo(3) = False And Wert = True Then
                    B += 16
                End If
            Case 4
                If Bo(4) = True And Wert = False Then
                    B -= 8
                ElseIf Bo(4) = False And Wert = True Then
                    B += 8
                End If
            Case 5
                If Bo(5) = True And Wert = False Then
                    B -= 4
                ElseIf Bo(5) = False And Wert = True Then
                    B += 4
                End If
            Case 6
                If Bo(6) = True And Wert = False Then
                    B -= 2
                ElseIf Bo(6) = False And Wert = True Then
                    B += 2
                End If
            Case 7
                If Bo(7) = True And Wert = False Then
                    B -= 1
                ElseIf Bo(7) = False And Wert = True Then
                    B += 1
                End If
        End Select
    End Sub
    ''' <summary>
    ''' Lässt den KIThread einschlafen
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub KIPause()
        Try
            Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
        Catch
            FailedRestartingThread = False
            KIZieht = False
        End Try
    End Sub
    ''' <summary>
    ''' Sorgt dafür das wir warten und dann denn Einheiten Befehl ausführen.
    ''' </summary>
    ''' <param name="Befehl"></param>
    ''' <param name="Zeit"></param>
    ''' <remarks></remarks>
    Public Sub AufBefehlEndeWarten(ByVal Befehl As KIModiExtern, ByVal Zeit As Integer, ByVal Wait As Boolean)
        KIModusEinheitenBefehl = Befehl
        If Wait Then
            KIWarten(Zeit)
        Else
            If Objektverwalter.Spielfeld.Laufen IsNot Nothing Then
                Objektverwalter.Spielfeld.Laufen.Laufen()
                Objektverwalter.Spielfeld.Laufen.Zielerreicht = True
            End If

        End If
        DoBefehl(Wait)
    End Sub
    ''' <summary>
    ''' Veranlasst die KI nichts zu tun und zu warten
    ''' </summary>
    ''' <param name="Frames"></param>
    ''' <remarks></remarks>
    Protected Sub KIWarten(ByVal Frames As Integer)
        Dim M As ObjektSpielMenü = Objektverwalter.Menü
        If Not M.Spielmodus = ObjektSpielMenü.Spielmodi.KOSprechen Then
            M.Spielmodus = ObjektSpielMenü.Spielmodi.Nichts
        End If
        If Hauptmenü.Aufzeichnungsspulen Then
            MaxKIWarteFrame = 0
        Else
            MaxKIWarteFrame = Frames
        End If
        KIZieht = True
        KIPause()

    End Sub

    Protected Sub CreateVirtuellesLeben()
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not E Is Nothing Then
                    E.VirtuellesLeben = E.Leben
                    E.VirtuellerMeistSchaden = 0
                End If
            Next
        Next
    End Sub
#End Region
#Region "Allgemeines"
    ''' <summary>
    ''' Die KI erschafft eine KO EInheit
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub KOEinheitErschaffen()
        Select Objektverwalter.Spielfeld.GetCommanderWarsModus
            Case CommanderWarsGameModi.AdvanceWarsDC, CommanderWarsGameModi.CommanderWars2
                If Spieler.KOS(0).GetKOEinheit Is Nothing Then
                    Dim E2 As ObjektEinheit = Nothing
                    Dim Ziel As New Point(-1, -1)
                    Dim WSS2 As Wegsuchsystem = Nothing
                    Dim Bew As Integer = 0
                    For Each Einheit In Einheiten
                        If ExistUnit(Einheit) Then
                            If Einheit.IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                                If Einheit.Kosten >= 6000 Then
                                    If Einheit.Kosten / 2 <= Objektverwalter.Spielfeld.AktuellerSpieler.Fonds Then
                                        Dim WSS As Wegsuchsystem = CreateWSS(Einheit)
                                        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                                            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                                                If Not E2 Is Nothing Then
                                                    If Einheit.Kosten >= E2.Kosten Then
                                                        If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                                                            If IsFeldLeer(X, Y, Einheit) Then
                                                                Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude
                                                                If Not G Is Nothing Then
                                                                    If G.GetSpieler.Team = Spieler.Team Then
                                                                        If E2.X = Einheit.X And E2.Y = Einheit.Y Then
                                                                            Dim B As Integer = WSS.getBewegungspunktekosten(X, Y)
                                                                            If G.Angriff = ObjektGebäude.Angriffe.HQ And B < Bew Then
                                                                                E2 = Einheit
                                                                                Ziel = New Point(X, Y)
                                                                                WSS2 = WSS
                                                                                Bew = B
                                                                            ElseIf G.GetBauliste().Contains(Einheit.EinheitenID) Then
                                                                                If B < Bew Then
                                                                                    E2 = Einheit
                                                                                    Ziel = New Point(X, Y)
                                                                                    WSS2 = WSS
                                                                                    Bew = B
                                                                                End If
                                                                            End If
                                                                        ElseIf G.GetBauliste.Contains(Einheit.EinheitenID) Or G.Angriff = ObjektGebäude.Angriffe.HQ Then
                                                                            If E2.Kosten < Einheit.Kosten Then
                                                                                E2 = Einheit
                                                                                Ziel = New Point(X, Y)
                                                                                WSS2 = WSS
                                                                                Bew = WSS.getBewegungspunktekosten(X, Y)
                                                                            End If
                                                                        End If
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                Else
                                                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                                                        If IsFeldLeer(X, Y, Einheit) Then
                                                            Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude
                                                            If Not G Is Nothing Then
                                                                If G.GetSpieler.Team = Spieler.Team Then
                                                                    If G.GetBauliste.Contains(Einheit.EinheitenID) Or G.Angriff = ObjektGebäude.Angriffe.HQ Then
                                                                        E2 = Einheit
                                                                        Ziel = New Point(X, Y)
                                                                        WSS2 = WSS
                                                                        Bew = WSS.getBewegungspunktekosten(X, Y)
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            Next
                                        Next
                                    End If
                                End If
                            End If
                        End If
                    Next
                    If Not E2 Is Nothing Then
                        If WSS2.getBewegungspunktekosten(Ziel.X, Ziel.Y, E2.GetMap) <= E2.Bewegungspunkte Then
                            Einheitauswählen(E2, Ziel, KIModiExtern.CreateKOEinheit, Nothing, WSS2, 4)
                        Else
                            Einheitauswählen(E2, Ziel, KIModiExtern.Warten, Nothing, WSS2, 4)
                        End If
                    End If
                End If
        End Select
        MomentaneEinheit = 0
    End Sub
    ''' <summary>
    ''' Sorgt dafür, dass die KI weiter zieht und zwar in dem sie die Schleife auf Null setzt...
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub EinheitGezogenVonVorneStarten()
        If KIModusIntern = KIModiIntern.Transproterziehen Then
            Select Case Spieler.KIStufe
                Case ObjektSpieler.KIStufen.Kinderleicht
                    GetAllUnits(EinheitenSortierKriterien.Zufall)
                Case ObjektSpieler.KIStufen.Einfach, ObjektSpieler.KIStufen.Normal
                    GetAllUnits(EinheitenSortierKriterien.GrößterBewegungsradius)
                Case ObjektSpieler.KIStufen.Mittel
                    GetAllUnits(EinheitenSortierKriterien.KleinsterBewegungsradius)
                Case Else
                    GetAllUnits(EinheitenSortierKriterien.Zufall)
            End Select
        End If
        KIModusIntern = KIModiIntern.GebäudeAngriff
        MomentaneEinheit = 0
    End Sub
    ''' <summary>
    ''' Gibt das momentane Ziel einer Einheit zurück.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetEinheitenZiel() As Point
        Return AktuelleZiel
    End Function
    ''' <summary>
    ''' Erschafft das Sichtfeld für eine Einheit.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <remarks></remarks>
    Protected Sub CreateEinheitenSicht(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer)
        Dim Sicht As Integer = Einheit.GetSicht(X, Y)
        If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeränderteWerte.SichtradiusVeränderung > 0 Then
            Sicht = Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeränderteWerte.SichtradiusVeränderung
        End If
        Dim Kreis(,) As Integer = Kreisfunktion(Sicht)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If X - Sicht + X1 >= 0 And X - Sicht + X1 < Objektverwalter.Spielfeld.Breite And Y - Sicht + Y1 >= 0 And Y - Sicht + Y1 < Objektverwalter.Spielfeld.Höhe Then
                    If Kreis(X1, Y1) >= 0 Then
                        If Kreis(X1, Y1) <= 1 Then
                            Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                        Else
                            If Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Tarnung = False Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsFlyingUnit Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - Sicht + X1, Y - Sicht + Y1) = True
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Erstellt die Sicht von Radar Gebäuden
    ''' </summary>
    ''' <param name="G"></param>
    ''' <remarks></remarks>
    Protected Sub CreateGebäudeSicht(ByVal G As ObjektGebäude)
        If G.Angriff = ObjektGebäude.Angriffe.Radar Then
            Dim X As Integer = G.Rechteck.X
            Dim Y As Integer = G.Rechteck.Y
            Dim Kreis(,) As Integer = Kreisfunktion(G.Reichweite)
            For X1 = 0 To Kreis.GetLength(0) - 1
                For Y1 = 0 To Kreis.GetLength(1) - 1
                    If Objektverwalter.Spielfeld.OnMap(X - G.Reichweite + X1, Y - G.Reichweite + Y1) Then
                        If Kreis(X1, Y1) > 0 Then
                            If Objektverwalter.Spielfeld.Landschaften(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).Tarnung = False Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - G.Reichweite + X1, Y - G.Reichweite + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - G.Reichweite + X1, Y - G.Reichweite + Y1) = True
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(G.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - G.Reichweite + X1, Y - G.Reichweite + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - G.Reichweite + X1, Y - G.Reichweite + Y1) = True
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Helikopter.tostring Or Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Flugzeug.tostring Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - G.Reichweite + X1, Y - G.Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - G.Reichweite + X1, Y - G.Reichweite + Y1) = True
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
    End Sub
    ''' <summary>
    ''' Erstellt die Sicht der Landschaft Feuer
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Sichtweite"></param>
    ''' <remarks></remarks>
    Protected Sub CreateFeuerSicht(ByVal X As Integer, ByVal Y As Integer, ByVal Sichtweite As Integer)
        Dim Kreis(,) As Integer = Kreisfunktion(Sichtweite)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= 0 Then
                    If Objektverwalter.Spielfeld.OnMap(X - Sichtweite + X1, Y - Sichtweite + Y1) Then
                        If Objektverwalter.Spielfeld.Landschaften(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Tarnung = False Then
                            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld)) = False Then
                                If Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                    Sichtfeld(X - Sichtweite + X1, Y - Sichtweite + Y1) = True
                                End If
                            Else
                                Sichtfeld(X - Sichtweite + X1, Y - Sichtweite + Y1) = True
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Reichweite"></param>
    ''' <param name="Alles">Wenn true werden auch alle Wälder aufgedeckt</param>
    ''' <remarks></remarks>
    Protected Sub UnfogArea(ByVal X As Integer, ByVal Y As Integer, ByVal Reichweite As Integer, ByVal Alles As Boolean)
        Dim Kreis(,) As Integer = Kreisfunktion(Reichweite)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Objektverwalter.Spielfeld.OnMap(X - Reichweite + X1, Y - Reichweite + Y1) Then
                    If Kreis(X1, Y1) > 0 Then
                        If Kreis(X1, Y1) > 0 Then
                            If Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Tarnung = False Or Alles = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(Spieler.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                                    End If
                                Else
                                    Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Helikopter.tostring Or Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Flugzeug.tostring Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Kreis(X1, Y1) = 0 Then
                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1) = True
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Erstellt die Landschaften die der Spieler sehen kann
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub CreateSicht()
        Dim RegenNebel As Boolean = False
        Select Case My.Settings.CommanderWarsGameMoodus
            Case CommanderWarsGameModi.AdvanceWarsDC, CommanderWarsGameModi.AdvanceWarsDS, CommanderWarsGameModi.CommanderWars2
                'In DS und DC müssen wir jetzt Nebel erzeugen.
                'Ich will aber nicht.
                'Hier geht es nicht um wollen sondern um die Regeln. Doof!
                If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Regen Then
                    RegenNebel = True
                End If
        End Select

        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                If Objektverwalter.Spielfeld.Regeln.Nebel > 0 Or RegenNebel Then
                    Sichtfeld(X, Y) = False
                ElseIf Not Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                    If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).IsGetarnt(Spieler.Spieler) = True Then
                        Sichtfeld(X, Y) = False
                    Else
                        Sichtfeld(X, Y) = True
                    End If
                Else
                    Sichtfeld(X, Y) = True
                End If
            Next
        Next
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                If IsNothing(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude) = False Then
                    If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude.Spieler).Team = Spieler.Team Then
                        Sichtfeld(X, Y) = True
                        CreateGebäudeSicht(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude)
                    End If
                End If
                If Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).LandschaftsID = "FEUER" Then
                    CreateFeuerSicht(X, Y, LandschaftsTexturFeuer.FeuerSicht)
                End If
                If IsNothing(AktuelleEinheit) Then
                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                        If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Spieler).Team = Spieler.Team Then
                            CreateEinheitenSicht(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld), X, Y)
                        End If
                    End If
                ElseIf X = AktuelleEinheit.X And Y = AktuelleEinheit.Y Then
                ElseIf X = AktuelleZiel.X And Y = AktuelleZiel.Y Then
                    CreateEinheitenSicht(AktuelleEinheit, AktuelleZiel.X, AktuelleZiel.Y)
                ElseIf IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                    If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Spieler).Team = Spieler.Team Then
                        CreateEinheitenSicht(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld), X, Y)
                    End If
                End If
            Next
        Next
        For I = 0 To Spieler.Sichtfelder.Length - 1
            If Spieler.Sichtfelder(I).Z = Schlachtfeld Then
                UnfogArea(Spieler.Sichtfelder(I).X, Spieler.Sichtfelder(I).Y, Spieler.Sichtfelder(I).W, True)
            End If
        Next
    End Sub
    ''' <summary>
    ''' Erstellt ein Wegsuchsystem für eine Runde.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CreateWSS(ByVal Einheit As ObjektEinheit) As Wegsuchsystem
        Dim WSS As Wegsuchsystem = Nothing
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange

        If Bewegunspunkte <= Einheit.Treibstoff Then
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
        ElseIf Einheit.Treibstoff = -1 Then
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
        Else
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
        End If
        Return WSS
    End Function
    ''' <summary>
    ''' erstellt ein Wegsuchsystem für n-Felder
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Reichweite"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CreateWSS(ByVal Einheit As ObjektEinheit, ByVal Reichweite As Integer) As Wegsuchsystem
        Return New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Reichweite)
    End Function
    ''' <summary>
    ''' Gibt eines der Gebäude das besetzt werden kann und Einheiten produzieren kann zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBauGebäudeZumBesetzen(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Felder As Point() = GetAllBesetzungsfelder(Einheit, WSS, False)
        Dim MomFeld As New Point(-1, -1)
        Dim LetzteGebäude As ObjektGebäude = Nothing
        Dim Wegkosten As Integer = -1
        For Each Feld In Felder
            Dim Gebäude As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Feld.X, Feld.Y, Schlachtfeld).Gebäude
            If Not Gebäude Is Nothing Then
                If Gebäude.GetBaulisteThisPlayer.Length > 0 Then
                    If MomFeld.X >= 0 Then
                        Select Case Besetzngspriorität
                            Case Besetzungsprioritäten.Keine
                                If Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                End If
                            Case Besetzungsprioritäten.FlughafebBasisHafenLaborHQStadt
                                If LetzteGebäude.GebäudeID = "FLUGHAFEN" Then
                                    If Gebäude.GebäudeID = "FLUGHAFEN" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "FLUGHAFEN" Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GebäudeID = "BASIS" Then
                                    If Gebäude.GebäudeID = "BASIS" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "BASIS" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GebäudeID = "WERFT" Then
                                    If Gebäude.GebäudeID = "WERFT" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "WERFT" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GebäudeID = "LABOR" Then
                                    If Gebäude.GebäudeID = "LABOR" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "LABOR" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GebäudeID = "HQ" Then
                                    If Gebäude.GebäudeID = "HQ" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "HQ" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GebäudeID = "STADT" Then
                                    If Gebäude.GebäudeID = "STADT" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebäude = Gebäude
                                    End If
                                ElseIf Gebäude.GebäudeID = "STADT" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                End If
                            Case Besetzungsprioritäten.MeisteEinheiten
                                If LetzteGebäude.GetBaulisteThisPlayer.Length < Gebäude.GetBaulisteThisPlayer.Length Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                ElseIf LetzteGebäude.GetBaulisteThisPlayer.Length = Gebäude.GetBaulisteThisPlayer.Length And Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebäude = Gebäude
                                End If
                        End Select
                    Else
                        MomFeld = Feld
                        LetzteGebäude = Gebäude
                    End If
                End If
            End If
        Next
        If MomFeld.X < 0 And Felder.Length > 0 Then
            MomFeld = Felder(Zufallszahl(0, Felder.Length - 1))
        End If
        Return MomFeld
    End Function
    ''' <summary>
    ''' Gibt eines der Gebäude zurück die die Besetzungskriterien am meisten Erfüllen von der Einheit entfernt sind, aber in dieser Runde besetzt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetWeitestesBesetzungsFeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Felder As Point() = GetAllBesetzungsfelder(Einheit, WSS, False)
        Dim MomFeld As New Point(-1, -1)
        Dim Wegkosten As Integer = -1
        For Each Feld In Felder
            Dim WKosten As Integer = WSS.getBewegungspunktekosten(Feld.X, Feld.Y)
            If WKosten > Wegkosten Then
                Wegkosten = WKosten
                MomFeld = Feld
            ElseIf WKosten = Wegkosten And Zufallszahl(0, 1) = 1 Then
                Wegkosten = WKosten
                MomFeld = Feld
            End If
        Next
        Return MomFeld
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurück die in dieser Runde besetzt werden können und frei sind.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <param name="MitEinheitdrauf">Wenn True werden alle Gebäude zurück gegeben die besetzt werden können auch wenn eine Einheit draufsteht</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllBesetzungsfelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing, Optional ByVal MitEinheitdrauf As Boolean = False) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.KannBesetzen = True Then
            'Wir initialiesieren evtl. das Wegsuchsystem.
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Höhe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                            Dim Gebäud As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlachtfeld).Gebäude
                            If Not Gebäud Is Nothing Then
                                If Objektverwalter.Spielfeld.Spieler(Gebäud.Spieler).Team <> Spieler.Team Then
                                    If Gebäud.Besetzung > 0 Or Gebäud.Angriff = ObjektGebäude.Angriffe.Silo Then
                                        If Felder.Contains(neuerPunkt) = False Then
                                            If MitEinheitdrauf = True Then
                                                Felder.Push(neuerPunkt)
                                            ElseIf Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                Felder.Push(neuerPunkt)
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt zurück wie groß der Geldschaden wäre wenn wir von diesem Feld aus angreifen würden.
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="ATKX"></param>
    ''' <param name="ATKY"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetGeldschaden(ByVal Angreifer As ObjektEinheit, ByVal ATKX As Integer, ByVal ATKY As Integer, ByVal Verteidiger As ObjektEinheit, ByRef TPDifferenz As Single) As Single
        Dim Glück As Point = Spieler.GetGlückPech(ATKX, ATKY)
        AktuelleZiel = New Point(ATKX, ATKY)
        If Glücksfaktor > 0 Then
            Glück.X *= Glücksfaktor
        Else
            Glück.X = Glück.Y * Glücksfaktor
        End If
        Dim OpferLeben As Single = Verteidiger.Leben
        Dim Schaden As Single = Objektverwalter.Schadensberechnung(Angreifer, ATKX, ATKY, Verteidiger.X, Verteidiger.Y, Angreifer.Leben, OpferLeben, True, Glück.X, Verteidiger)(0)
        Glück = Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).GetGlückPech(Verteidiger.X, Verteidiger.Y)
        If Glücksfaktor > 0 Then
            Glück.X *= Glücksfaktor
        Else
            Glück.X = Glück.Y * Glücksfaktor
        End If

        OpferLeben = Angreifer.Leben
        Dim EigenSchaden As Single = Objektverwalter.Schadensberechnung(Verteidiger, Verteidiger.X, Verteidiger.Y, ATKX, ATKY, Verteidiger.Leben - Schaden, OpferLeben, True, Glück.X, Angreifer)(0)
        Dim Verteidigerleben As Single = Verteidiger.Leben - Schaden
        If Schaden > Verteidiger.Leben Then
            Schaden = Verteidiger.Leben
            Verteidigerleben = 0
        End If
        TPDifferenz = Schaden - EigenSchaden
        Dim GegenSchaden As Single = EigenSchaden * Angreifer.Kosten * Spieler.Teurungsrate(Angreifer, ATKX, ATKY) * EigenerEinheitenWert
        Schaden = Verteidiger.Kosten * Schaden * Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Teurungsrate(Verteidiger, Verteidiger.X, Verteidiger.Y)

        If GegenSchaden <= 0 Or Verteidigerleben <= 0 Then
            Schaden /= 10000
            If Schaden < MinimalerGeldschaden Then
                Schaden = MinimalerGeldschaden
            End If
        Else
            Schaden = Schaden / GegenSchaden
        End If
        If Verteidiger.MaximaleReichweite > 1 Then
            Schaden += Verteidiger.Kosten / 1000
        End If
        Return Schaden
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfOpfer(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        Return GetBestesNahkampfOpfer(Einheit, WSS, GetAllNahKampffelder(Einheit, True, WSS))
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfOpfer(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem, ByVal Opfer() As Point2) As Point2
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = -1
            Dim MomentanerSchaden As Single = 0
            Dim MomentaneTPDifferenz As Single = -100
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).Point2.X, Opfer(I).Point2.Y, Schlachtfeld)
                'Wir berechnen wie viel Geldschaden wir anrichten würden
                Dim TPDifferenz As Single = 0
                Dim Schaden As Single = GetGeldschaden(Einheit, Opfer(I).Point1.X, Opfer(I).Point1.Y, UnserOpfer, TPDifferenz)
                Select Case OpferBerechnung
                    Case GeldTPAngriffsModus.NurTP
                        If TPDifferenz > MinimaleTPDifferenz Then
                            If TPDifferenz > MomentaneTPDifferenz Then
                                MomentaneTPDifferenz = TPDifferenz
                                MomentanesOpfer = I
                            ElseIf TPDifferenz = MomentaneTPDifferenz And Zufallszahl(0, 1) = 1 Then
                                MomentaneTPDifferenz = TPDifferenz
                                MomentanesOpfer = I
                            End If
                        End If
                    Case GeldTPAngriffsModus.Beides
                        If TPDifferenz > MinimaleTPDifferenz Then
                            If Schaden >= MinimalerGeldschaden Then
                                If TPDifferenz > MomentaneTPDifferenz And Schaden > MomentanerSchaden Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                ElseIf TPDifferenz = MomentaneTPDifferenz And Schaden >= MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                ElseIf TPDifferenz >= MomentaneTPDifferenz And Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                End If
                            End If
                        End If
                    Case GeldTPAngriffsModus.NurGeld
                        If Schaden >= MinimalerGeldschaden Then
                            If Schaden > MomentanerSchaden Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            End If
                        End If
                End Select
            Next
            If MomentanesOpfer < 0 Then
                Return New Point2(New Point(-1, -1), New Point(-1, -1))
            Else
                Return Opfer(MomentanesOpfer)
            End If
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfOpfer(ByVal Einheit As ObjektEinheit) As Point
        Return GetBestesFernkampfOpfer(Einheit, GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, True))
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück. Berechnet nach dem Geldschaden.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfOpfer(ByVal Einheit As ObjektEinheit, ByVal Opfer() As Point) As Point
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = 0
            Dim MomentanerSchaden As Integer = 0
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).X, Opfer(I).Y, Schlachtfeld)
                If Not UnserOpfer Is Nothing Then
                    Dim Glück As Point = Spieler.GetGlückPech(Einheit.X, Einheit.Y)
                    If Glücksfaktor > 0 Then
                        Glück.X *= Glücksfaktor
                    Else
                        Glück.X = Glück.Y * Glücksfaktor
                    End If
                    Dim OpferLeben As Single = UnserOpfer.Leben
                    Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Einheit.X, Einheit.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, True, Glück.X, UnserOpfer)(0)
                    If Schaden > MomentanerSchaden Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    End If
                Else
                    'Wir greifen ein Gebäude oder eine Landschaft an.
                    If Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Leben > 0 Then
                        If MomentanerSchaden = 0 Then
                            If MomentanesOpfer <> 0 Then
                                If Zufallszahl(0, 1) = 0 Then
                                    MomentanesOpfer = I
                                End If
                            Else
                                MomentanesOpfer = I
                            End If
                        End If
                    Else
                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Gebäude
                        Dim Schaden As Integer = ObjektLadeklasse.GetGebäudeKosten(G.GebäudeID, G.Spieler) / G.GetMaxLeben * Tabellenverwalter.GetWert(Einheit.Waffe2, "Gebäude")
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                End If
            Next
            Return Opfer(MomentanesOpfer)
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück. Berechnet nach dem Geldschaden aber primäres Ziel sind Fernwaffen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Overridable Function GetBestesFernkampfOpferFirstFernwaffen(ByVal Einheit As ObjektEinheit, ByVal Opfer() As Point) As Point
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = -1
            Dim MomentanerSchaden As Integer = 0
            Dim Fernwaffe As Boolean = False 'Haben wir schon eine Fernwaffe gefunden?
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).X, Opfer(I).Y, Schlachtfeld)
                If Not UnserOpfer Is Nothing Then
                    Dim Glück As Point = Spieler.GetGlückPech(Einheit.X, Einheit.Y)
                    If Glücksfaktor > 0 Then
                        Glück.X *= Glücksfaktor
                    Else
                        Glück.X = Glück.Y * Glücksfaktor
                    End If
                    Dim OpferLeben As Single = UnserOpfer.Leben
                    Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Einheit.X, Einheit.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, True, Glück.X, UnserOpfer)(0)
                    If Fernwaffe = False Then
                        If UnserOpfer.MaximaleReichweite > 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                            Fernwaffe = True
                        Else
                            If Schaden > MomentanerSchaden Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            End If
                        End If
                    ElseIf UnserOpfer.MaximaleReichweite > 1 Then
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                Else
                    'Wir greifen ein Gebäude oder eine Landschaft an.
                    If Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Leben > 0 Then
                        If MomentanerSchaden = 0 Then
                            If MomentanesOpfer < 0 Then
                                MomentanesOpfer = I
                            ElseIf Zufallszahl(0, 1) = 0 Then
                                MomentanesOpfer = I
                            End If
                        End If
                    Else
                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Gebäude
                        Dim Schaden As Integer = ObjektLadeklasse.GetGebäudeKosten(G.GebäudeID, G.Spieler) / G.GetMaxLeben * Tabellenverwalter.GetWert(Einheit.Waffe2, "Gebäude")
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                End If
            Next
            If MomentanesOpfer >= 0 Then
                Return Opfer(MomentanesOpfer)
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurück die in diesem Zug per Nahkampf erreicht werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampffelder(ByVal Einheit As ObjektEinheit, Optional ByVal NurMitFeind As Boolean = True, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Höhe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                    If ExistFeld(Felder, New Point2(neuerPunkt, neuerPunkt)) = False Then
                                        If NurMitFeind = False Then
                                            Felder.Push(New Point2(neuerPunkt, neuerPunkt))
                                        Else
                                            GetNahAngriffsFelderVonFeld(Einheit, neuerPunkt, Felder)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    ElseIf neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                        Dim X2 As Integer = X1
                        Dim Y2 As Integer = Y1
                        For I = 0 To 3
                            Select Case I
                                Case 0
                                    X2 -= 1
                                Case 1
                                    X2 += 1
                                    Y2 -= 1
                                Case 2
                                    X2 += 1
                                    Y2 += 1
                                Case 3
                                    X2 -= 1
                                    Y2 += 1
                            End Select
                            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                                Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                Dim P2 As New Point(X2, Y2)
                                If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                    If P2.X >= 0 And P2.X < Objektverwalter.Spielfeld.Breite And P2.Y >= 0 And P2.Y < Objektverwalter.Spielfeld.Höhe Then
                                        If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                            If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                                If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                    If NurMitFeind = True Then
                                                        If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), False, P2) = True Then
                                                                    Felder.Push(New Point2(P2, neuerPunkt))
                                                                End If
                                                            End If
                                                        End If
                                                    Else
                                                        Felder.Push(New Point2(P2, neuerPunkt))
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurück die in diesem Zug per Nahkampf erreicht werden können und nicht von Fernwaffen unseres Typs beschossen werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampffelderWithNoIndirectFire(ByVal Einheit As ObjektEinheit, Optional ByVal NurMitFeind As Boolean = True, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Höhe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then

                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                    If ExistFeld(Felder, New Point2(neuerPunkt, neuerPunkt)) = False Then
                                        If NurMitFeind = False Then
                                            Felder.Push(New Point2(neuerPunkt, neuerPunkt))
                                        Else
                                            GetNahAngriffsFelderVonFeld(Einheit, neuerPunkt, Felder)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    ElseIf neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                        Dim X2 As Integer = X1
                        Dim Y2 As Integer = Y1
                        For I = 0 To 3
                            Select Case I
                                Case 0
                                    X2 -= 1
                                Case 1
                                    X2 += 1
                                    Y2 -= 1
                                Case 2
                                    X2 += 1
                                    Y2 += 1
                                Case 3
                                    X2 -= 1
                                    Y2 += 1
                            End Select
                            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                                Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                Dim P2 As New Point(X2, Y2)
                                If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                    If P2.X >= 0 And P2.X < Objektverwalter.Spielfeld.Breite And P2.Y >= 0 And P2.Y < Objektverwalter.Spielfeld.Höhe Then
                                        If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                            If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                                If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                    If NurMitFeind = True Then
                                                        If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), False, P2) = True Then
                                                                    Felder.Push(New Point2(P2, neuerPunkt))
                                                                End If
                                                            End If
                                                        End If
                                                    Else
                                                        Felder.Push(New Point2(P2, neuerPunkt))
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt die Felder zurück die von diesem Feld aus angegriffen werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="neuerPunkt"></param>
    ''' <param name="Felder"></param>
    ''' <remarks></remarks>
    Protected Sub GetNahAngriffsFelderVonFeld(ByVal Einheit As ObjektEinheit, ByVal neuerPunkt As Point, ByRef Felder As Stack(Of Point2))
        Dim X2 As Integer = neuerPunkt.X
        Dim Y2 As Integer = neuerPunkt.Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                Dim P2 As New Point(X2, Y2)
                If Sichtfeld(P2.X, P2.Y) = True Then
                    If ExistFeld(Felder, New Point2(neuerPunkt, P2)) = False Then
                        If Not Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld) Is Nothing Then
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld), False, neuerPunkt) = True Then
                                    Felder.Push(New Point2(neuerPunkt, P2))
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurück die von einem Punkt beschossen werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="NurMitFeind">Gibt nur die Felder zurück auf denen ein Feind steht.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfFelder(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer, Optional ByVal NurMitFeind As Boolean = True) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                    If Felder.Contains(neuerPunkt) = False Then
                                        If NurMitFeind = True Then
                                            If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                                    Felder.Push(neuerPunkt)
                                                End If
                                            End If
                                        Else
                                            Felder.Push(neuerPunkt)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurück die Angegriffen werden können.
    ''' Wenn keine Einheiten gefunden werden suchen wir Gebäude.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfFelderGebäude(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer, Optional ByVal NurMitFeind As Boolean = True) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            For X1 = 0 To MaximaleReichweite * 2
                For Y1 = 0 To MaximaleReichweite * 2
                    If Kreis(X1, Y1) >= MinimaleReichweite Then
                        Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                            If Sichtfeld(neuerPunkt.X, neuerPunkt.Y) = True Then
                                If Felder.Contains(neuerPunkt) = False Then
                                    If NurMitFeind = True Then
                                        If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                            If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                                Felder.Push(neuerPunkt)
                                            End If
                                        End If
                                    Else
                                        Felder.Push(neuerPunkt)
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
            If Felder.Count = 0 Then
                'Jetzt suchen wir Gebäude
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            If Objektverwalter.Spielfeld.OnMap(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1) Then
                                If Spieler.NeutraleGebäudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1, Schlachtfeld).Leben > 0 Then
                                        Felder.Push(New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1))
                                    Else
                                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1, Schlachtfeld).Gebäude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.KP > 0 Then
                                                    Felder.Push(New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1))
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlachtfeld).Gebäude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.KP > 0 Then
                                                Felder.Push(New Point(X1, Y1))
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer zurück wen wir uns vor dem Schießen noch bewegen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfFeldmitBewegung(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        Dim Opfer() As Point2 = GetAllFernkampfFeldermitBewegung(Einheit, WSS)
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = 0
            Dim MomentanerSchaden As Integer = 0
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).Point2.X, Opfer(I).Point2.Y, Schlachtfeld)
                Dim Glück As Point = Spieler.GetGlückPech(Opfer(I).Point1.X, Opfer(I).Point1.Y)
                If Glücksfaktor > 0 Then
                    Glück.X += Glücksfaktor
                Else
                    Glück.X = Glück.Y * Glücksfaktor
                End If
                Dim OpferLeben As Single = UnserOpfer.Leben
                Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Opfer(I).Point1.X, Opfer(I).Point1.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, True, Glück.X, UnserOpfer)(0)
                If Schaden > MomentanerSchaden Then
                    MomentanerSchaden = Schaden
                    MomentanesOpfer = I
                ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                    MomentanerSchaden = Schaden
                    MomentanesOpfer = I
                End If
            Next
            Return Opfer(MomentanesOpfer)
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurück die durch ziehen und schießen mit einer Fernwaffe beschoßen werden können.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernkampfFeldermitBewegung(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Einheit.MaximaleReichweite > 1 Then
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Höhe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                'So dieses Feld kann betreten werden und jetzt schießen wir von ihm aus.
                                Dim Felder2 As Point() = GetAllFernKampfFelder(Einheit, neuerPunkt.X, neuerPunkt.Y, True)
                                For Each Feld In Felder2
                                    Felder.Push(New Point2(neuerPunkt, Feld))
                                Next
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Überprüft ob ein Feld bereits einem Array hinzugefügt wurden ist
    ''' </summary>
    ''' <param name="Felder"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistFeld(ByVal Felder As Point(), ByVal Feld As Point) As Boolean
        For Each F In Felder
            If F.X = Feld.X And F.Y = Feld.Y Then
                Return True
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurück ob ein Doppelpunkt m Array enthalten ist
    ''' </summary>
    ''' <param name="Felder"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistFeld(ByVal Felder As Stack(Of Point2), ByVal Feld As Point2) As Boolean
        For Each NFeld In Felder
            If NFeld.Point1.X = Feld.Point1.X Then
                If NFeld.Point1.Y = Feld.Point1.Y Then
                    If NFeld.Point2.X = Feld.Point2.X Then
                        If NFeld.Point2.Y = Feld.Point2.Y Then
                            Return True
                        End If
                    End If
                End If
            End If
        Next
        Return False
    End Function

    ''' <summary>
    ''' Gibt zurück ob die Einheit von unserer Angegriffen werden kann.
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannAngegriffenWerden(ByVal Angreifer As ObjektEinheit, ByVal Verteidiger As ObjektEinheit, ByVal Fernkampf As Boolean, ByVal Pos As Point) As Boolean
        If ExistUnit(Verteidiger) Then
            If Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Team <> Spieler.Team Then
                Dim Distanz As Integer
                If Pos.X >= 0 Then
                    Distanz = Verteidiger.GetDistance(Pos)
                Else
                    Distanz = Angreifer.GetDistance(Verteidiger)
                End If
                If Not Angreifer.Waffe1 = "Keine" Then
                    If Distanz = 1 Then
                        If Tabellenverwalter.GetWert(Angreifer.Waffe1, Verteidiger.EinheitenID) >= 0 Then
                            Return True
                        ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                            If Fernkampf Then
                                If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                        Return True
                                    End If
                                End If
                            ElseIf Not Fernkampf Then
                                If Distanz = 1 Then
                                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                        Return True
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                        If Fernkampf Then
                            If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                                If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                    Return True
                                End If
                            End If
                        ElseIf Not Fernkampf Then
                            If Distanz = 1 Then
                                If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                    Return True
                                End If
                            End If
                        End If
                    End If
                ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                    If Fernkampf Then
                        If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                            If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                Return True
                            End If
                        End If
                    ElseIf Not Fernkampf Then
                        If Distanz = 1 Then
                            If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurück ob die Einheit von unserer Angegriffen werden kann, berücksichtigt nicht die Entfernung
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannAngegriffenWerden(ByVal Angreifer As ObjektEinheit, ByVal Verteidiger As ObjektEinheit) As Boolean
        If Not Verteidiger Is Nothing Then
            If Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Team <> Spieler.Team Then
                If Not Angreifer.Waffe1 = "Keine" Then
                    If Tabellenverwalter.GetWert(Angreifer.Waffe1, Verteidiger.EinheitenID) >= 0 Then
                        Return True
                    ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                        If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                            Return True
                        Else
                            Return False
                        End If
                    End If
                ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                        Return True
                    Else
                        Return False
                    End If
                Else
                    Return False
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurück auf das wir ziehen sollten um möglichst bald angreifen zu können. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestenNahkampfFeind(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim Ziel2 As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        Dim MomentaneWegkosten2 As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            Dim BewMax As Integer = 0
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim Bew As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y), False)
                    If Bew > 0 Then
                        'Wir können das Feld erreichen
                        If KannNahkampfvonFeldgemachtwerden(Einheit, X, Y) = True Then
                            If Bew < MomentaneWegkosten And Bew > BewMax Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            ElseIf Bew = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            ElseIf MomentaneWegkosten = -1 Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            End If
                        End If
                    End If
                Next
            Next
        End If
        If MomentaneWegkosten2 - MomentaneWegkosten > Einheit.GetMovementRange * 2 And Ziel2.X >= 0 Then
            Return Ziel2
        ElseIf MomentaneWegkosten < 0 And MomentaneWegkosten2 >= 0 Then
            Return Ziel2
        Else
            Return Ziel
        End If
    End Function
    ''' <summary>
    ''' Gibt das Feld zurück auf das wir ziehen sollten um möglichst bald angreifen zu können. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestenFeindVonGebäude(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            Dim BewMax As Integer = Einheit.GetMovementRange
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim Bew As Integer = WSS.getBewegungspunktekosten(X, Y)
                    If Bew >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir können das Feld erreichen
                            If KannNahkampfGemachtwerden(Einheit, X, Y) = True Then
                                If Bew < MomentaneWegkosten And Bew > BewMax Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                ElseIf Bew = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Überprüft ob per Nahangriff eine Einheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfvonFeldgemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        Dim P As New Point(X, Y)
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlachtfeld), False, P) = True Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Überprüft ob per Nahangriff eine Einheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfGemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        Dim P As New Point(X, Y)
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlachtfeld)) = True Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurück auf das wir laufen sollten, weil wir weiter laufen wollen als wir können
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetZielFeldfürdieseRunde(ByRef WSS As Wegsuchsystem, ByVal Ziel As Point, ByVal Einheit As ObjektEinheit) As Point
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        WSS.Ziel(Ziel.X, Ziel.Y, True)
        Return New Point(WSS.WegpunkteX(WSS.WegpunkteX.Length - 1), WSS.WegpunkteY(WSS.WegpunkteY.Length - 1))
    End Function
    ''' <summary>
    ''' Sucht die näheste Besetzung und gibt das näheste freie Feld zurück auf das wir in diesem Zug ziehen müssen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähesteBesetzung(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir können das Feld erreichen
                            If IsBesetzungDrauf(X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt zurück ob auf diesem Feld ein Gebäude ist, dass besetzt werden kann.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function IsBesetzungDrauf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude
        If G Is Nothing Then
            Return False
        Else
            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                If G.IsBesetzung(Spieler.Spieler) = True Then
                    Return True
                End If
            Else
                Return False
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt eines der nähesten Felder zurück von dem aus ohne Bewegung in der nächsten Runde angegriffen werden könnte.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestesFernkampffeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MaximaleReichweite > 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) = True Then
                            'Wir können das Feld erreichen
                            If KannFernkampfGemachtWerden(Einheit, X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgeführt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannFernkampfGemachtWerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim Felder As Point() = {}
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                    If Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                            Return True
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt die Reichweite der Einheit zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBewegungspunkte(ByVal Einheit As ObjektEinheit) As Integer
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        Return Bewegunspunkte
    End Function
    ''' <summary>
    ''' Gibt an ob das Feld leer ist
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer, ByVal AktuelleEinheit As ObjektEinheit) As Boolean
        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
            Return True
        Else
            If X = AktuelleEinheit.X And Y = AktuelleEinheit.Y Then
                Return True
            Else
                Return False
            End If
        End If
    End Function
    ''' <summary>
    ''' Gibt zurück ob das Feld leer ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer) As Boolean
        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) Then
            Return True
        ElseIf Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Leben <= 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Überprüft ob die Einheit noch lebt und ob sie Nicht nichts ist
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistUnit(ByVal Einheit As ObjektEinheit) As Boolean
        If Not Einheit Is Nothing Then
            If Einheit.Leben > 0 Then
                If Einheit.X >= 0 And Einheit.Y >= 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Einheit.X, Einheit.Y, Schlachtfeld)
                    If E Is Nothing Then
                        Return False
                    ElseIf E.Equals(Einheit) Then
                        Return True
                    End If
                Else
                    Return False
                End If
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt alle freien Felder zurück die Leer sind und in dieser Runde betreten werden können.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetFreeFelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point()
        Dim Felder As New Stack(Of Point)
        'Wir haben eine Nahkampfeinheit
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        If WSS Is Nothing Then
            If Bewegunspunkte <= Einheit.Treibstoff Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
            ElseIf Einheit.Treibstoff = -1 Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
            Else
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
            End If
        End If
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                    If WSS.getBewegungspunktekosten(X, Y) <= Einheit.GetMovementRange Then
                        'Das Feld ist betretbar und frei?
                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                            Felder.Push(New Point(X, Y))
                        End If
                    End If
                End If
            Next
        Next
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt das beste Ziel für einen Angriff zurück.
    ''' Achtung: Bei Laser, Schocklaser, Monolith, Kristall wird immer das Gebäude zurück gegeben als Ziel.
    ''' -1,-1 Bedeutet kein Ziel
    ''' </summary>
    ''' <param name="Gebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestesGebäudeFeuer(ByVal Gebäude As ObjektGebäude) As Point
        Dim Punkt As New Point(-1, -1)
        Select Case Gebäude.Angriff
            Case ObjektGebäude.Angriffe.SchussN
                Return GetBestesSchussZiel(Gebäude)
            Case ObjektGebäude.Angriffe.SchussO
                Return GetBestesSchussZiel(Gebäude)
            Case ObjektGebäude.Angriffe.SchussS
                Return GetBestesSchussZiel(Gebäude)
            Case ObjektGebäude.Angriffe.SchussW
                Return GetBestesSchussZiel(Gebäude)
            Case ObjektGebäude.Angriffe.DreiStrahlN
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case ObjektGebäude.Angriffe.DreiStrahlO
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case ObjektGebäude.Angriffe.DreiStrahlS
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case ObjektGebäude.Angriffe.DreiStrahlW
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case ObjektGebäude.Angriffe.Strahl
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case ObjektGebäude.Angriffe.Kreis
                Return New Point(Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
            Case Else
                Return Punkt
        End Select
    End Function
    ''' <summary>
    ''' Gibt das Zielfeld zurück bei welchem wir den meisten Geldschaden verursachen.
    ''' </summary>
    ''' <param name="Gebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestesSchussZiel(ByVal Gebäude As ObjektGebäude) As Point
        Dim Ziele As Point() = Gebäude.GeschützZiele
        'So auf diese Felder kann geschoßen werden
        Dim BestesZiel As Integer = -1
        Dim Geldschaden As Integer = 0
        If Ziele.Length > 0 Then
            'wir suchen uns das beste Ziel.
            For I = 0 To Ziele.Length - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Ziele(I).X, Ziele(I).Y, Schlachtfeld)
                If Sichtfeld(Ziele(I).X, Ziele(I).Y) = True Then
                    Dim Damage As Single = 0
                    If E.Leben - Gebäude.Schaden * 10 < 1 Then
                        Damage = E.Leben
                    Else
                        Damage = Gebäude.Schaden * 10
                    End If
                    Dim MomGeldschaden As Integer = E.Kosten * Damage * Objektverwalter.Spielfeld.Spieler(E.Spieler).Teurungsrate(E, Gebäude.Rechteck.X, Gebäude.Rechteck.Y)
                    If MomGeldschaden > Geldschaden Then
                        Geldschaden = MomGeldschaden
                        BestesZiel = I
                    ElseIf MomGeldschaden = Geldschaden And Zufallszahl(0, 1) = 1 Then
                        Geldschaden = MomGeldschaden
                        BestesZiel = I
                    End If
                End If
            Next
            If BestesZiel >= 0 Then
                Return Ziele(BestesZiel)
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt den Ort zurück, wo wir den meisten Geldschaden mit einer Rakete verursachen würden.
    ''' </summary>
    ''' <param name="Radius"></param>
    ''' <param name="Schaden"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestenEinschlagsOrt(ByVal Radius As Integer, ByVal Schaden As Integer) As Point
        Dim MomZiel As New Point(-1, -1)
        Dim Geld As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim Geld2 As Integer = GetSchadeninGeld(X, Y, Schaden, Radius)
                If Geld < Geld2 Then
                    Geld = Geld2
                    MomZiel = New Point(X, Y)
                ElseIf Geld = Geld2 And Zufallszahl(0, 1) = 1 Then
                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                        Geld = Geld2
                        MomZiel = New Point(X, Y)
                    End If
                End If
            Next
        Next
        Return MomZiel
    End Function
    ''' <summary>
    ''' Gibt zurück wie viel Schaden an dieser Stelle durch eine Rakete verursacht würde
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Schaden"></param>
    ''' <param name="Radius"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetSchadeninGeld(ByVal X As Integer, ByVal Y As Integer, ByVal Schaden As Integer, ByVal Radius As Integer) As Integer
        Dim Geld As Integer = 0
        Dim Kreis(,) As Integer = Kreisfunktion(Radius)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= 0 Then
                    If X - Radius + X1 >= 0 And X - Radius + X1 < Objektverwalter.Spielfeld.Breite And Y - Radius + Y1 >= 0 And Y - Radius + Y1 < Objektverwalter.Spielfeld.Höhe Then
                        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld)) = False Then
                            Dim VerlorenesLeben As Integer = Schaden
                            If VerlorenesLeben - Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP > 0 Then
                                If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP > 1 Then
                                    VerlorenesLeben = Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP
                                End If
                            End If
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Spieler).Team = Objektverwalter.Spielfeld.AktuellerSpieler.Team Then
                                Geld -= Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kosten * VerlorenesLeben / 10 * 3
                            Else
                                Geld += Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kosten * VerlorenesLeben / 10
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Geld
    End Function
    ''' <summary>
    ''' Gibt zurück welche Einheiten mit dieser Fabrik gebaut werden sollten, sodass alle Tore benutzt werden und dabei möglichst viele Fonds ausgegeben werden.
    ''' </summary>
    ''' <param name="Fabrik"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function BestesGeldAusgebenBeiFabrik(ByVal Fabrik As GebäudeFabrik) As String()
        Dim MomBauEinheiten() As String = New String() {"", "", ""}
        Dim MomFonds As Integer = 0
        Dim MomEinheitenZahl As Integer = 0
        Dim Fabrikfonds As Integer = Fabrik.Variablen(1).Wert
        Dim Tor1() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X - 1, Fabrik.Rechteck.Y + 2)
        Dim Tor2() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X, Fabrik.Rechteck.Y + 2)
        Dim Tor3() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X + 1, Fabrik.Rechteck.Y + 2)
        If Fabrikfonds > 0 Then
            'wir überprüfen mehrere Möglichkeiten.
            If Tor1.Length > 0 Then
                For I = 0 To Tor1.Length - 1
                    Dim Kosten As Integer = ObjektLadeklasse.GetEinheitenkosten(Tor1(I)) * Spieler.Teurungsrate(Tor1(I), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                    Dim EinheitenZahl As Integer = 0
                    If Kosten <= Fabrikfonds Then
                        EinheitenZahl += 1
                        Dim Kosten2 As Integer = Kosten
                        If Tor2.Length > 0 Then
                            For I2 = 0 To Tor2.Length - 1
                                Kosten2 += ObjektLadeklasse.GetEinheitenkosten(Tor2(I2)) * Spieler.Teurungsrate(Tor2(I2), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                If Kosten2 <= Fabrikfonds Then
                                    EinheitenZahl += 1
                                    Dim Kosten3 As Integer = Kosten2
                                    For I3 = 0 To Tor3.Length - 1
                                        Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                        If Kosten3 <= Fabrikfonds Then
                                            EinheitenZahl += 1
                                            If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                                MomFonds = Kosten3
                                                MomEinheitenZahl = EinheitenZahl
                                                MomBauEinheiten = New String() {Tor1(I), Tor2(I2), Tor3(I3)}
                                            ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                                MomFonds = Kosten3
                                                MomEinheitenZahl = EinheitenZahl
                                                MomBauEinheiten = New String() {Tor1(I), Tor2(I2), Tor3(I3)}
                                            End If
                                        End If
                                    Next
                                End If
                            Next
                        Else
                            Dim Kosten3 As Integer = Kosten2
                            If Tor3.Length > 0 Then
                                For I3 = 0 To Tor3.Length - 1
                                    Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                    If Kosten3 <= Fabrikfonds Then
                                        EinheitenZahl += 1
                                        If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                            MomFonds = Kosten3
                                            MomEinheitenZahl = EinheitenZahl
                                            MomBauEinheiten = New String() {Tor1(I), "", Tor3(I3)}
                                        ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                            MomFonds = Kosten3
                                            MomEinheitenZahl = EinheitenZahl
                                            MomBauEinheiten = New String() {Tor1(I), "", Tor3(I3)}
                                        End If
                                    End If
                                Next
                            Else
                                If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {Tor1(I), "", ""}
                                ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {Tor1(I), "", ""}
                                End If
                            End If
                        End If
                    End If
                Next
            Else
                Dim EinheitenZahl As Integer = 0
                Dim Kosten2 As Integer = 0
                If Tor2.Length > 0 Then
                    For I2 = 0 To Tor2.Length - 1
                        Kosten2 += ObjektLadeklasse.GetEinheitenkosten(Tor2(I2)) * Spieler.Teurungsrate(Tor2(I2), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                        If Kosten2 <= Fabrikfonds Then
                            EinheitenZahl += 1
                            Dim Kosten3 As Integer = Kosten2
                            For I3 = 0 To Tor3.Length - 1
                                Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                If Kosten3 <= Fabrikfonds Then
                                    EinheitenZahl += 1
                                    If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                        MomFonds = Kosten3
                                        MomEinheitenZahl = EinheitenZahl
                                        MomBauEinheiten = New String() {"", Tor2(I2), Tor3(I3)}
                                    ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                        MomFonds = Kosten3
                                        MomEinheitenZahl = EinheitenZahl
                                        MomBauEinheiten = New String() {"", Tor2(I2), ""}
                                    End If
                                End If
                            Next
                        End If
                    Next
                Else
                    Dim Kosten3 As Integer = Kosten2
                    If Tor3.Length > 0 Then
                        For I3 = 0 To Tor3.Length - 1
                            Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                            If Kosten3 <= Fabrikfonds Then
                                EinheitenZahl += 1
                                If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {"", "", Tor3(I3)}
                                ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {"", "", Tor3(I3)}
                                End If
                            End If
                        Next
                    End If
                End If
            End If
        End If
        Return MomBauEinheiten
    End Function
    ''' <summary>
    ''' Gibt ein Ziel für ein Höllium zurück.
    ''' </summary>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestesHölliumZiel(ByVal Höllium As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim LetzteWegkosten As Integer = -1
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim Wegkosten As Integer = WSS.getBewegungspunktekosten(X, Y)
                If Wegkosten >= 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Not E Is Nothing Then
                        If Objektverwalter.Spielfeld.Spieler(E.Spieler).Team <> Spieler.Team Then
                            If LetzteWegkosten < 0 Then
                                LetzteWegkosten = Wegkosten
                                Ziel = New Point(X, Y)
                            ElseIf Wegkosten < LetzteWegkosten Then
                                LetzteWegkosten = Wegkosten
                                Ziel = New Point(X, Y)
                            ElseIf Wegkosten = LetzteWegkosten Then
                                If E.Kosten > Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld).Kosten Then
                                    LetzteWegkosten = Wegkosten
                                    Ziel = New Point(X, Y)
                                ElseIf E.Kosten = Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld).Kosten And Zufallszahl(0, 1) = 1 Then
                                    LetzteWegkosten = Wegkosten
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt zurück welche Infanteristen von diesem Gebäude gebaut werden können.
    ''' </summary>
    ''' <param name="BauGebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildInfis(ByVal BauGebäude As ObjektGebäude) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebäude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebäude.CanBuildUnit(BListe(I)) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Gibt zurück welche Infanteristen von diesem Gebäude gebaut werden können.
    ''' </summary>
    ''' <param name="BauGebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildInfis(ByVal BauGebäude As ObjektGebäude, ByVal Prüffonds As Integer) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebäude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebäude.CanBuildUnit(BListe(I), Prüffonds) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Berechnet wie viele Züge wir bräuchten um unser Ziel zu erreichen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <param name="Ziel"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CalculateZugDauer(ByVal Einheit As ObjektEinheit, ByVal WSS As Wegsuchsystem, ByVal Ziel As Point) As Integer
        Dim Bew As Integer = Einheit.GetMovementRange
        If Bew <= 0 Then
            Return -1
        End If

        Dim Dau As Integer = WSS.getBewegungspunktekosten(Ziel.X, Ziel.Y)
        If Dau < 0 Then Return -1
        Dim R As Integer = 0
        Dim Tage As Integer = Math.DivRem(Dau, Bew, R)
        If R > 0 Then
            Tage += 1
        End If
        Return Tage
    End Function
    ''' <summary>
    ''' Berechnet wie viele Züge wir bräuchten um unser Ziel zu erreichen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CalculateZugDauer(ByVal Einheit As ObjektEinheit, ByVal BewKosten As Integer) As Integer
        If BewKosten < 0 Then Return -1
        Dim Bew As Integer = Einheit.GetMovementRange
        If Bew <= 0 Then
            Return -1
        End If

        Dim R As Integer = 0
        Dim Tage As Integer = Math.DivRem(BewKosten, Bew, R)
        If R > 0 Then
            Tage += 1
        End If
        Return Tage
    End Function
    ''' <summary>
    ''' Überprüft ob wenn wir die Einheit bauen sie sich bewegen kann.
    ''' UV
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function CanMoveAfterBuilding(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Einheit.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler
        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebäude
        If G IsNot Nothing Then
            For I = 0 To G.CanMoveAfterBuilding.Count - 1
                If G.CanMoveAfterBuilding(I).Name = Einheit.EinheitenID Then
                    If G.CanMoveAfterBuilding(I).Wert > 0 Then
                        Return True
                    Else
                        Return False
                    End If
                End If
            Next
        End If
        Dim WSS As New Wegsuchsystem(Einheit, X, Y, Schlachtfeld, , False)
        If WSS.WegsuchenDauer(Einheit.GetMovementRange + 1) Then
            G.CanMoveAfterBuilding.Add(New ObjektGebäude.Variable(Einheit.EinheitenID, 1))
            Return True
        End If
        G.CanMoveAfterBuilding.Add(New ObjektGebäude.Variable(Einheit.EinheitenID, -1))
        Return False
    End Function
    ''' <summary>
    ''' Mal sehen ob die Einheit einen Gegner Angreifen kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CanAttackAfterBuilding(ByVal Einheit As ObjektEinheit) As Boolean
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not E Is Nothing Then
                    If E.GetSpieler.Team <> Spieler.Team Then
                        If Einheit.IsAttackable(E, False) Then
                            Return True
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurück ob dieses Gebäude Infis bauen kann.
    ''' </summary>
    ''' <param name="BauGebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CanBuildInfi(ByVal BauGebäude As ObjektGebäude) As Boolean
        If BauGebäude.CanBuildUnit("INF") Or BauGebäude.CanBuildUnit("SSIEINHEIT") Or BauGebäude.CanBuildUnit(MovementSorts.MECH.tostring.toupper) Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurück ob das Feld von einer bestimmten Einheit beschossen werden kann.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="BeschussArt"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsBeschussFeldVon(ByVal X As Integer, ByVal Y As Integer, ByVal BeschussArt As BeschussArten) As Boolean
        Return GetBoolean(Beschußfelder(X, Y))(BeschussArt)
    End Function
    ''' <summary>
    ''' Die KI zieht auf der anderen Schlacht.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Overridable Sub Schlachtwechsel(ByVal Sortieren As EinheitenSortierKriterien)
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then
            'Sorgt für einen Schlachtwechsel der KI.
            If Schlachtfeld = ObjektSpielfeld.Bodenschlacht Then
                Schlachtfeld = ObjektSpielfeld.Luftschlacht
            Else
                Schlachtfeld = ObjektSpielfeld.Bodenschlacht
            End If

            Objektverwalter.Spielfeld.SchlachtWechseln()
            GetAllUnits(Sortieren)
            GetAllBuildings()
            CreateSicht()
            GetBeschußfelder()
        End If
    End Sub
    ''' <summary>
    ''' Zieht die Einheiten welche die KI nicht steuern soll
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub ExternGesteurteEinheiten()
        Dim I As Integer = 0
        While I < Spieler.ExternGezogeneEinheiten.Length
            Dim E As ObjektEinheit = Spieler.ExternGezogeneEinheiten(I).Einheit
            If ExistUnit(E) Then
                If E.HatsichBewegt = False Then
                    Select Case Spieler.ExternGezogeneEinheiten(I).Befehl
                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.WartenBisAngriff

                            If Not E Is Nothing Then

                                If E.HatsichBewegt = False Then
                                    If E.Treibstoff > 0 Then
                                        If E.MaximaleReichweite > 1 Then
                                            Dim WSS As Wegsuchsystem = CreateWSS(E)
                                            'OH je  das wird noch komplikate
                                            If Spieler.KOS(0).MoveandFire = True And Spieler.KOS(0).FireandMove = True Then
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                                                    DoNächsterBefehlExternGezogen(I)
                                                    Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                    If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                        'So wir haben ein Opfer.
                                                        NächsterBefehl(Felder.Point1, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), KIModiExtern.Angriff, WSS, 4)
                                                    End If
                                                Else
                                                    Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                    If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                        'So wir haben ein Opfer.
                                                        Einheitauswählen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                                                        DoNächsterBefehlExternGezogen(I)
                                                    End If
                                                End If
                                                EinheitAbwählen()
                                            ElseIf Spieler.KOS(0).MoveandFire = True Then
                                                'Ein Angriff ziehen und Feuern wie beim Nahkampf
                                                Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                    'So wir haben ein Opfer.
                                                    Einheitauswählen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                                                    DoNächsterBefehlExternGezogen(I)
                                                End If
                                            ElseIf Spieler.KOS(0).FireandMove = True Then
                                                'Wir suchen uns ein Opfer
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                                                    DoNächsterBefehlExternGezogen(I)
                                                End If
                                                'wir haben unser Opfer angegriffen jetzt sollten wir die Einheit noch ziehen.
                                                WSS = New Wegsuchsystem(E, E.X, E.Y, E.GetMap, -1)
                                                Dim Ziel As Point = GetNähestesFernkampffeld(E, WSS)
                                                If Ziel.X >= 0 Then
                                                    If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing Then
                                                        Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS)
                                                        DoNächsterBefehlExternGezogen(I)
                                                    Else
                                                        NächsterBefehl(Ziel, Nothing, KIModiExtern.Warten, WSS, 4)
                                                    End If
                                                Else
                                                    EinheitAbwählen()
                                                End If
                                            Else
                                                'Das ist mir die liebste und einfachst Situation Uff.
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                                                    DoNächsterBefehlExternGezogen(I)
                                                End If
                                            End If
                                        ElseIf E.MinimaleReichweite = 1 Or E.Waffe1 = "Keine" Then
                                            'Wir lassen sie einen Nahkampf machen.
                                            Dim WSS As Wegsuchsystem = CreateWSS(E)
                                            Dim Feld As Point2 = GetBestesNahkampfOpfer(E, WSS)
                                            If Feld.Point1.X >= 0 And Feld.Point2.X >= 0 Then
                                                Einheitauswählen(E, Feld.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.Point2.X, Feld.Point2.Y, Schlachtfeld), WSS, 4)
                                                DoNächsterBefehlExternGezogen(I)
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.Bauen

                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.Heilen
                            If E.getKP >= 9 Then
                                DoNächsterBefehlExternGezogen(I)
                            Else
                                'Mal sehen ob wir klug angreifen können.
                                If E.MaximaleReichweite > 1 Then
                                    Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                    Dim WSS As Wegsuchsystem = CreateWSS(E)
                                    If Feld.X >= 0 Then
                                        Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                                    Else
                                        Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS, 2)
                                    End If
                                Else
                                    'Nahkämpfer warten momentan nur
                                    Dim WSS As Wegsuchsystem = CreateWSS(E)
                                    Einheitauswählen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS, 2)
                                End If
                            End If
                    End Select
                End If
            Else
                RemoveEinheit(I)
            End If
            I += 1
        End While
        KIModusIntern = KIModiIntern.Besetzen
    End Sub
    ''' <summary>
    ''' Führt den nächsten Befehl aus.
    ''' </summary>
    ''' <param name="I"></param>
    ''' <remarks></remarks>
    Private Sub DoNächsterBefehlExternGezogen(ByRef I As Integer)
        Select Case Spieler.ExternGezogeneEinheiten(I).NächsterBefehl
            Case ObjektSpieler.ExternGezogeneEinheit.NächsteBefehle.Entfernen
                Spieler.ExternGezogeneEinheiten(I) = Spieler.ExternGezogeneEinheiten(Spieler.ExternGezogeneEinheiten.Length - 1)
                Array.Resize(Spieler.ExternGezogeneEinheiten, Spieler.ExternGezogeneEinheiten.Length - 1)
                I -= 1
        End Select
    End Sub
    Private Sub RemoveEinheit(ByVal I As Integer)
        Spieler.ExternGezogeneEinheiten(I) = Spieler.ExternGezogeneEinheiten(Spieler.ExternGezogeneEinheiten.Length - 1)
        Array.Resize(Spieler.ExternGezogeneEinheiten, Spieler.ExternGezogeneEinheiten.Length - 1)
        I -= 1
    End Sub
    ''' <summary>
    ''' Also los!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ZumNähestenHQZiehen(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Z As Point = New Point(-1, -1)
        Dim Distanz As Integer = -1
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim HQ As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, ObjektSpielfeld.Bodenschlacht).Gebäude
                If HQ IsNot Nothing Then
                    If HQ.Angriff = ObjektGebäude.Angriffe.HQ Then
                        If HQ.Spieler > 0 Then
                            If HQ.GetSpieler.Team <> Einheit.GetSpieler.Team Then
                                Dim D As Integer = WSS.getBewegungspunktekosten(X, Y, ObjektSpielfeld.Bodenschlacht)
                                If D > 0 Then
                                    If Distanz < 0 Then
                                        Distanz = D
                                        Z = New Point(X, Y)
                                    ElseIf D < Distanz Then
                                        Distanz = D
                                        Z = New Point(X, Y)
                                    ElseIf D = Distanz And Zufallszahl(0, 2) = 0 Then
                                        Distanz = D
                                        Z = New Point(X, Y)
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Z
    End Function
    Protected MustOverride Function CalculateRealZiel(ByRef WSS As Wegsuchsystem, ByVal Ziel As Point, ByVal Einheit As ObjektEinheit, ByRef Opfer As Point) As Point

#Region "Gebäude Angriff durch Einheiten"
    ''' <summary>
    ''' Gibt ein Gebäude zurück das von dieser Einheit von der momentanen Position zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfGebäude(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        If Einheit.CanAttackBuilding Then
            Dim Opfer() As Point2 = GetAllNahKampfGebäudefelder(Einheit, WSS)
            If Opfer.Length > 0 Then
                Dim MomentanesOpfer As Integer = Zufallszahl(0, Opfer.Length - 1)
                If MomentanesOpfer < 0 Then
                    Return New Point2(New Point(-1, -1), New Point(-1, -1))
                Else
                    Return Opfer(MomentanesOpfer)
                End If
            Else
                Return New Point2(New Point(-1, -1), New Point(-1, -1))
            End If
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurück die in diesem Zug per Nahkampf erreicht werden können mit Gebäude drauf.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampfGebäudefelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Höhe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                GetNahAngriffsGebäudeFelderVonFeld(Einheit, neuerPunkt, Felder)
                            End If
                        End If
                    ElseIf neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                        Dim X2 As Integer = X1
                        Dim Y2 As Integer = Y1
                        For I = 0 To 3
                            Select Case I
                                Case 0
                                    X2 -= 1
                                Case 1
                                    X2 += 1
                                    Y2 -= 1
                                Case 2
                                    X2 += 1
                                    Y2 += 1
                                Case 3
                                    X2 -= 1
                                    Y2 += 1
                            End Select
                            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                                Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                Dim P2 As New Point(X2, Y2)
                                If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                    If P2.X >= 0 And P2.X < Objektverwalter.Spielfeld.Breite And P2.Y >= 0 And P2.Y < Objektverwalter.Spielfeld.Höhe Then
                                        If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                            If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                If Spieler.NeutraleGebäudeAngriff = True Then
                                                    If Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Leben > 0 Then
                                                        Felder.Push(New Point2(neuerPunkt, P2))
                                                    Else
                                                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebäude
                                                        If Not G Is Nothing Then
                                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                                If G.KP > 0 Then
                                                                    Felder.Push(New Point2(neuerPunkt, P2))
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                Else
                                                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebäude
                                                    If Not G Is Nothing Then
                                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                            If G.KP > 0 Then
                                                                Felder.Push(New Point2(neuerPunkt, P2))
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt die Felder zurück die von diesem Feld aus angegriffen werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="neuerPunkt"></param>
    ''' <param name="Felder"></param>
    ''' <remarks></remarks>
    Protected Sub GetNahAngriffsGebäudeFelderVonFeld(ByVal Einheit As ObjektEinheit, ByVal neuerPunkt As Point, ByRef Felder As Stack(Of Point2))
        Dim X2 As Integer = neuerPunkt.X
        Dim Y2 As Integer = neuerPunkt.Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If X2 >= 0 And Y2 >= 0 And X2 < Objektverwalter.Spielfeld.Breite And Y2 < Objektverwalter.Spielfeld.Höhe Then
                Dim P2 As New Point(X2, Y2)
                If Sichtfeld(P2.X, P2.Y) = True Then
                    If ExistFeld(Felder, New Point2(neuerPunkt, P2)) = False Then
                        If Spieler.NeutraleGebäudeAngriff = True Then
                            If Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Leben > 0 Then
                                Felder.Push(New Point2(neuerPunkt, P2))
                            Else
                                Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebäude
                                If Not G Is Nothing Then
                                    If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                        If G.KP > 0 Then
                                            Felder.Push(New Point2(neuerPunkt, P2))
                                        End If
                                    End If
                                End If
                            End If
                        Else
                            Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebäude
                            If Not G Is Nothing Then
                                If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                    If G.KP > 0 Then
                                        Felder.Push(New Point2(neuerPunkt, P2))
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurück.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurück wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfGebäude(ByVal Einheit As ObjektEinheit) As Point
        If Einheit.CanAttackBuilding Then
            Dim Opfer() As Point = GetAllFernKampfGebäudeFelder(Einheit, Einheit.X, Einheit.Y)
            If Opfer.Length > 0 Then
                Return Opfer(Zufallszahl(0, Opfer.Length - 1))
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurück die von einem Punkt beschossen werden können
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfGebäudeFelder(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Felder.Contains(neuerPunkt) = False Then
                                    If Spieler.NeutraleGebäudeAngriff = True Then
                                        If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                            Felder.Push(neuerPunkt)
                                        Else
                                            Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                            If Not G Is Nothing Then
                                                If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                    If G.KP > 0 Then
                                                        Felder.Push(neuerPunkt)
                                                    End If
                                                End If
                                            End If
                                        End If
                                    Else
                                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.KP > 0 Then
                                                    Felder.Push(neuerPunkt)
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt eines der nähesten Felder zurück von dem aus ohne Bewegung in der nächsten Runde angegriffen werden könnte.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestesFernkampfGebäudefeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.CanAttackBuilding Then
            If Einheit.MaximaleReichweite > 1 Then
                If WSS Is Nothing Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
                End If
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Höhe
                        If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                            If IsFeldLeer(X, Y, Einheit) = True Then
                                'Wir können das Feld erreichen
                                If KannFernkampfGebäudeGemachtWerden(Einheit, X, Y) = True Then
                                    If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    ElseIf MomentaneWegkosten = -1 Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgeführt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannFernkampfGebäudeGemachtWerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Stelle As Integer = Array.IndexOf(Objektverwalter.Spielfeld.AktuellerSpieler.KOS(0).WetterartfürSenker, Objektverwalter.Spielfeld.Regeln.Wetter)
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Spieler.NeutraleGebäudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                        Return True
                                    Else
                                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.KP > 0 Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.KP > 0 Then
                                                Return True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurück auf das wir ziehen sollten um möglichst bald angreifen zu können. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNähestenNahkampfGebäude(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir können das Feld erreichen
                            If KannNahkampfGebäudevonFeldgemachtwerden(Einheit, X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgeführt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfGebäudevonFeldgemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            If MaximaleReichweite > 1 Then
                Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If neuerPunkt.X >= 0 And neuerPunkt.X < Objektverwalter.Spielfeld.Breite And neuerPunkt.Y >= 0 And neuerPunkt.Y < Objektverwalter.Spielfeld.Höhe Then
                                If Spieler.NeutraleGebäudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                        Return True
                                    Else
                                        Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.KP > 0 Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebäude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.KP > 0 Then
                                                Return True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Lohnt es sich überhaupt Landeboote zu bauen?
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function IsLandeBootBauSinnvoll() As Boolean
        For Each G In Gebäude
            If TypeOf G Is GebäudeHafen Then
                If G.Spieler = Spieler.Spieler Then
                    For Each Unit In Objektverwalter.Spielfeld.Einheiten
                        If Unit IsNot Nothing Then
                            If Unit.Spieler = Spieler.Spieler Then
                                If Unit.CanAttack Then
                                    Dim WSS As New Wegsuchsystem(Unit, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
                                    If WSS.Wegsuchen(True, Unit.KannBesetzen) < 0 Then
                                        Return True
                                    End If
                                End If
                            End If
                        End If
                    Next
                    Return False
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Entfernt alle Gebäude, die nichts bauen können
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub TrimGebäude()
        Dim G2 As New Stack(Of ObjektGebäude)
        For I = 0 To Gebäude.Length - 1
            If Gebäude(I).GetBaulisteThisPlayer.Length > 0 Then
                G2.Push(Gebäude(I))
            End If
        Next
        Gebäude = G2.ToArray
    End Sub
#End Region
#End Region
#Region "Transport System"
    ''' <summary>
    ''' Zieht die Transporter und entlädt Einheiten.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub TransporterZiehen(ByVal Sortieren As EinheitenSortierKriterien)
        Dim Entladen As Boolean = False
        While MomentaneEinheit < Einheiten.Length
            Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
            If ExistUnit(Einheit) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheit.Ladung.Length > 0 Then
                        'Es ist ein Transporter, es kann hier auch passieren, dass Transporter verladen werden.
                        'Zuerst finden wir heraus ob die Einheit eine Fracht hat.
                        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1, False)
                        Dim Ziel As Stack(Of Point2) = GetTransporterZiel(Einheit, WSS)
                        If Ziel(0).Point1.X >= 0 Then
                            If ContainsZiel(Ziel) Then
                                If IsInfiTransporter(Einheit) And Einheit.GetGeladeneEinheitenZahl = 1 Then
                                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Ziel(0).Point1.X, Ziel(0).Point1.Y, Schlachtfeld).Gebäude
                                    If G IsNot Nothing Then
                                        If G.IsBesetzung(Einheit.Ladung(0)) Then
                                            Dim G2 As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Ziel(0).Point2.X, Ziel(0).Point2.Y, Schlachtfeld).Gebäude
                                            If G2 IsNot Nothing Then
                                                If G2.IsBesetzung(Einheit.Ladung(0)) Then
                                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                                Else
                                                    Dim Z As Point2 = Ziel.Pop
                                                    Ziel.Push(New Point2(Z.Point2, Z.Point1))
                                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                                End If
                                            Else
                                                Dim Z As Point2 = Ziel.Pop
                                                Ziel.Push(New Point2(Z.Point2, Z.Point1))
                                                TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                            End If
                                        Else
                                            TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                        End If
                                    Else
                                        TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                    End If
                                Else
                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                End If
                            Else
                                Dim Ziel2 As Point = CalculateRealZiel(WSS, Ziel(0).Point1, Einheit, New Point)
                                Einheitauswählen(Einheit, Ziel2, KIModiExtern.Warten, Nothing, WSS, 4)
                            End If
                            Entladen = True
                        End If
                    Else
                        If TransporterVerladen(Einheit) Then
                            Exit Sub
                        Else 'Einfach warten!
                            Einheitauswählen(Einheit, New Point(Einheit.X, Einheit.Y), KIModiExtern.Warten, Nothing, Nothing, 4)
                            EinheitGezogenVonVorneStarten()
                            Exit Sub
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        If Entladen Then
            GetAllUnits(Sortieren)
            EinheitGezogenVonVorneStarten()
            Exit Sub
        End If
    End Sub
    Private Sub TransportZiehenUndEntladen(ByVal Einheit As ObjektEinheit, ByVal Ziel As Stack(Of Point2), ByVal WSS As Wegsuchsystem)
        Dim ErsterZug As Boolean = True
        Dim BewZiel As Point = Ziel(0).Point1
        Dim Truppe As Integer = 0
        While Ziel.Count > 0
            Dim Z As Point2 = Ziel.Pop
            'Selbes Entladungsfeld
            If Z.Point1 = BewZiel Then
                'es kann entladen werden
                If Z.Point2.X >= 0 Then
                    Dim Gegner As New EinheitAmphibienpanzer(1, Z.Point2.X, Z.Point2.Y)
                    AngreiferSchaden = Truppe
                    If ErsterZug Then
                        Einheitauswählen(Einheit, BewZiel, KIModiExtern.Entladen, Gegner, WSS, 4)
                        ErsterZug = False
                    Else
                        NächsterBefehl(BewZiel, Gegner, KIModiExtern.Entladen, WSS, 4)
                    End If
                    'Etwas reduzieren, da ja die Truppen aufrücken.
                    Truppe -= 1
                End If
            End If
            Truppe += 1
        End While
        'Fertig gezogen.
        If Objektverwalter.Spielfeld.AktuelleEinheit IsNot Nothing Then
            NächsterBefehl(BewZiel, Nothing, KIModiExtern.Warten, WSS, 4)
        End If
    End Sub
    Protected Function TransporterVerladen(ByVal Einheit As ObjektEinheit) As Boolean
        If Not Einheit.HatsichBewegt Then
            Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            Dim Ziel As Vector3 = GetTransporter(Einheit, WSS)
            'Wir haben einen Transporter gefunden!
            If Ziel.X >= 0 Then
                If Ziel.Z >= 0 Then
                    'Wir können ihn erreichen!
                    If Ziel.Z = 0 Then
                        'Sogar ihn dieser Runde!
                        Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Fracht, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    Else
                        Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    End If
                Else
                    'Leider ist er noch zu weit weg!
                    Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                    EinheitGezogenVonVorneStarten()
                    Return True
                End If
            Else
                If Not Einheit.HatsichBewegt Then
                    'schauen wir mal ob unter uns ein Gebäude ist
                    Dim Gebäude As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Einheit.X, Einheit.Y, Schlachtfeld).Gebäude
                    If Not Gebäude Is Nothing Then
                        If Gebäude.GetBaulisteThisPlayer.Length > 0 And Spieler.Team = Objektverwalter.Spielfeld.Spieler(Gebäude.Spieler).Team Then
                            Dim Ziele As Point() = GetFreeFelder(Einheit, WSS)
                            If Ziele.Length > 0 Then
                                Einheitauswählen(Einheit, Ziele(Zufallszahl(0, Ziele.Length - 1)), KIModiExtern.Warten, Nothing, WSS, 4)
                                EinheitGezogenVonVorneStarten()
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Wo hin man ziehen soll wenn wir einen Transporter haben!
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporterZiel(ByVal Transporter As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Stack(Of Point2)
        Dim Ziel As New Stack(Of Point2)
        If Not Transporter.HatsichBewegt Then
            Dim TWegsuchsysteme As New Stack(Of Wegsuchsystem)
            If Transporter.HasLadung Then
                Dim L As ObjektLandschaft = Nothing
                'Wo sollen wir entladen?
                For Each Ladung In Transporter.Ladung
                    If Ladung IsNot Nothing Then
                        Ladung.X = -1
                        Ladung.Y = -1
                        TWegsuchsysteme.Push(New Wegsuchsystem(Ladung, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren))
                    End If
                Next
                'So zuerst das Wegsuchsystem ausbreiten
                WSS.BerechnungsStart(Transporter, -1, True)
                Dim TWSSS As Wegsuchsystem() = TWegsuchsysteme.ToArray
                'Jetzt alle Startfelder bestimmen
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                        If WSS.getBewegungspunktekosten(X, Y, Schlachtfeld) >= 0 Then
                            L = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld)
                            If Transporter.EntladungsUntergrund.Contains(L.getID) Then
                                L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                Do Until L Is Nothing
                                    For Each TWSS In TWSSS
                                        If TWSS.Einheit.CanMoveOverTile(L.KooX, L.KooY, Schlachtfeld) Then
                                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                                                Dim Start As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                                                'Je nach Anzahl der Runden die wir brauchen um hier hin zu kommen kommt eine andere Startzahl rein!
                                                'Wir erstellen den Wegsucher und schreiben die Zeit rein!
                                                TWSS.setWegsucher(X, Y, Schlachtfeld, (Start * TWSS.Einheit.GetMovementRange) + 1)
                                            End If
                                        End If
                                    Next
                                    L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop
                            End If
                        End If
                    Next
                Next
                Dim Z As New Stack(Of Point)
                Dim Dauer As New Stack(Of Integer)
                'Für jedes Wegsuchsystem dem Weg zum Feind suchen.
                For Each TWSS In TWSSS
                    If TWSS.Einheit.KannBesetzen Then
                        If TWSS.Einheit.CanAttack Then
                            Z.Push(TWSS.WegsuchenTransporter(True, True))
                            Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                        Else
                            Z.Push(TWSS.WegsuchenTransporter(False, True))
                            Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                        End If
                    ElseIf TWSS.Einheit.CanAttack Then
                        Z.Push(TWSS.WegsuchenTransporter(True, False))
                        Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                    Else
                        Z.Push(TWSS.WegsuchenTransporter(True, True))
                        Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                    End If
                Next

                'Für jedes Ziel schauen ob es ein nützliches Ziel ist.
                Dim BesteZielLandschaft As ObjektLandschaft = Nothing
                Dim MaxDauer As Integer = -1
                Dim Entladungsplätze As Integer = 0
                'Hier sollte man am besten noch schauen was das beste Feld ist!
                'Ideal wäre alle Entladungsfelder durch gehen und schauen ob wir Runden mäßig hier am wenigsten Zeit brauchen!
                For I = 0 To Z.Count - 1
                    Dim D As Integer = Dauer(I)
                    Dim P As Point = Z(I)
                    If P.X >= 0 Then
                        If TWSSS(I).Ziel(P.X, P.Y, Schlachtfeld, True, , False) Then
                            Dim TStelle As Integer = TWSSS(I).WegpunkteX.Length - 1
                            'Schauen von welchem Feld aus wir entladen!
                            If TStelle < 0 Then
                                L = Objektverwalter.Spielfeld.Landschaften(P.X, P.Y, Schlachtfeld)
                            Else
                                L = Objektverwalter.Spielfeld.Landschaften(TWSSS(I).WegpunkteX(TStelle), TWSSS(I).WegpunkteY(TStelle), Schlachtfeld)
                            End If
                            If WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 And Transporter.EntladungsUntergrund.Contains(L.getID) And (Not (TWSSS(I).Einheit.KannBesetzen And IsInfiTransporter(Transporter))) Then
                                'Auch ein Ziel!
                                Dim TDauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld), False)
                                If TDauer > D Then D = TDauer
                                'Sind wir schneller dort?
                                If D <= MaxDauer Or MaxDauer < 0 Then
                                    'In dieser Runde?
                                    If MaxDauer = 0 Then
                                        Dim EFelder As Integer = GetEntladungsFelder(Transporter, L)
                                        'Können wir mehr Truppen entladen?
                                        If EFelder > Entladungsplätze Then
                                            'Unser neues Ziel!
                                            MaxDauer = D
                                            BesteZielLandschaft = L
                                            Entladungsplätze = EFelder
                                        End If
                                    Else
                                        'Dann brauchen wir noch etwas!
                                        MaxDauer = D
                                        BesteZielLandschaft = L
                                        Entladungsplätze = 0
                                    End If
                                End If
                            Else
                                Dim SPunkt As New Point(L.KooX, L.KooY)
                                L = Wegsuchsystem.getFeldRundrum(SPunkt.X, SPunkt.Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                Do Until L Is Nothing
                                    If WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                        If Transporter.EntladungsUntergrund.Contains(L.getID) Then
                                            'Dies ist ein Feld von dem wir können drauf und auch entladen!
                                            Dim TDauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld), False)
                                            If TDauer > D Then D = TDauer
                                            'Sind wir schneller dort?
                                            If D <= MaxDauer Or MaxDauer < 0 Then
                                                'In dieser Runde?
                                                If MaxDauer = 0 Then
                                                    Dim EFelder As Integer = GetEntladungsFelder(Transporter, L)
                                                    'Können wir mehr Truppen entladen?
                                                    If EFelder > Entladungsplätze Then
                                                        'Unser neues Ziel!
                                                        MaxDauer = D
                                                        BesteZielLandschaft = L
                                                        Entladungsplätze = EFelder
                                                    End If
                                                Else
                                                    'Dann brauchen wir noch etwas!
                                                    MaxDauer = D
                                                    BesteZielLandschaft = L
                                                    Entladungsplätze = 0
                                                End If
                                            End If
                                        End If
                                    End If
                                    L = Wegsuchsystem.getFeldRundrum(SPunkt.X, SPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop
                            End If
                        End If
                    End If
                Next
                'So Ziel gefunden und los geht es!
                L = BesteZielLandschaft
                If L IsNot Nothing Then
                    WSS.Ziel(L.KooX, L.KooY, Schlachtfeld, True)
                    'Weg zum Ziel berechnen!
                    If WSS.WegpunkteX(0) = L.KooX Then
                        If WSS.WegpunkteY(0) = L.KooY Then
                            'So wir können das Ziel erreichen in dieser Runde.
                            Dim ZPunkt As Point = New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0))
                            For I2 = 0 To TWSSS.Length - 1
                                L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                'Truppen entladungsfelder berechnen
                                Dim ErstesZiel As New Point2(ZPunkt, New Point(-1, -1))
                                Do Until L Is Nothing
                                    If TWSSS(I2).getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                        If Objektverwalter.Spielfeld.Einheiten(L.KooX, L.KooY, Schlachtfeld) Is Nothing Then
                                            'Hoffentlich entladen wir auf dieses Feld nichts!
                                            For Each P In Ziel
                                                If P.Point2.X = L.KooX Then
                                                    If P.Point2.X = L.KooX Then
                                                        'Nächste Landschaft und erneut prüfen
                                                        L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                                        Continue Do
                                                    End If
                                                End If
                                            Next
                                            'Feld gefunden nächstes Feld
                                            If ErstesZiel.Point2.X < 0 Then
                                                ErstesZiel.Point2 = New Point(L.KooX, L.KooY)
                                            Else
                                                If TWSSS(I2).WegpunkteX.Contains(L.KooX) And TWSSS(I2).WegpunkteY.Contains(L.KooY) Then
                                                    ErstesZiel.Point2 = New Point(L.KooX, L.KooY)
                                                End If
                                            End If
                                        End If
                                    End If
                                    L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop

                                'Nichts gefunden die Einheit kann nicht entladen werden.
                                Ziel.Push(ErstesZiel)
                            Next
                        Else
                            'Wir brauchen noch ein paar Runden
                            'Nur das Ziel zurück geben
                            Ziel.Push(New Point2(New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0)), New Point(-1, -1)))
                        End If
                    Else
                        'Nur das Ziel zurück geben
                        Ziel.Push(New Point2(New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0)), New Point(-1, -1)))
                    End If
                Else
                    MoveUnitToTransporter(Transporter)
                End If
            Else 'Wir wollen Truppen beladen.
                WSS.BerechnungsStart(Transporter, , True)
                'Alle Truppen sammeln die geladen werden können oder sollen
                Dim ZielWSSs As New Stack(Of Wegsuchsystem)
                For Each Unit In Einheiten
                    If ExistUnit(Unit) Then
                        If Transporter.IsLoadable(Unit) = True Then
                            Dim NWSS As New Wegsuchsystem(Unit, , False)
                            Dim Dauer As Integer = CalculateZugDauer(Unit, NWSS.Wegsuchen(True, Unit.KannBesetzen))
                            If Unit.KannBesetzen Then
                                If Dauer > 2 Or Dauer < 0 Then
                                    ZielWSSs.Push(NWSS)
                                End If
                            ElseIf Dauer < 0 Then
                                ZielWSSs.Push(NWSS)
                            End If
                        End If
                    End If
                Next
                'Truppen verladenungsziel bestimmen.
                Dim V As Vector4 = GetMinimaleDauer(ZielWSSs, WSS)
                Ziel.Push(New Point2(New Point(V.X, V.Y), New Point(-1, -1)))
            End If
        Else
            Ziel.Push(New Point2(New Point(-1, -1), New Point(-1, -1)))
        End If
        Dim Ziel2 As New Stack(Of Point2)
        While Ziel.Count > 0
            Dim Z As Point2 = Ziel.Pop
            If Z.Point1 = Z.Point2 Then
                Z.Point2 = New Point(-1, -1)
            End If
            Ziel2.Push(Z)
        End While
        Return Ziel2
    End Function
    Public Function IsInfiTransporter(ByVal T As ObjektEinheit)
        If TypeOf T Is EinheitTTP Then
            Return True
        ElseIf TypeOf T Is EinheitTTL Then
            Return True
        ElseIf TypeOf T Is EinheitTransporthelikopter Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Berechnet die Dauer die man minimal braucht damit sich die beiden Truppen treffen.
    ''' </summary>
    ''' <param name="ZielWSSs"></param>
    ''' <returns>X=Koo;Y=Koo;Z=Dauer;W=ZielWSSs Index</returns>
    ''' <remarks></remarks>
    Public Function GetMinimaleDauer(ByVal ZielWSSs As Stack(Of Wegsuchsystem), ByVal WSS As Wegsuchsystem) As Vector4
        Dim V As New Vector4(-1, -1, -1, -1)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                Dim Dauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                If Dauer >= 0 Then
                    If Dauer < V.Z Or V.Z < 0 Then
                        Dim Dauer2 As Integer = Dauer
                        Dim ZIndex As Integer = -1
                        For I = 0 To ZielWSSs.Count - 1
                            Dim Dauer3 As Integer = ZielWSSs(I).getRundeDiskret(ZielWSSs(I).getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                            If ZIndex < 0 Then
                                If Dauer3 >= 0 Then
                                    If Dauer3 > Dauer Then
                                        Dauer2 = Dauer3
                                        ZIndex = I
                                    Else
                                        ZIndex = I
                                    End If
                                End If
                            Else
                                If Dauer3 >= 0 Then
                                    If Dauer3 >= Dauer Then
                                        If Dauer3 < Dauer2 Then
                                            ZIndex = I
                                            Dauer2 = Dauer3
                                        End If
                                    End If
                                End If
                            End If
                        Next
                        If ZIndex >= 0 Then
                            V = New Vector4(X, Y, Dauer2, ZIndex)
                        End If
                    End If
                End If
            Next
        Next
        Return V
    End Function
    ''' <summary>
    ''' Überprüft ob mindestens ein P.Point2 ein Feld ist!
    ''' </summary>
    ''' <param name="P"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ContainsZiel(ByVal P As Stack(Of Point2)) As Boolean
        For Each P2 In P
            If P2.Point2.X >= 0 Then
                If P2.Point2.Y >= 0 Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Wie viele Felder können mit Truppen beladen werden?
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetEntladungsFelder(ByVal Transporter As ObjektEinheit, ByVal Feld As ObjektLandschaft) As Integer
        Dim EFelder As Integer = 0
        Dim EntladeneTruppen As New Stack(Of Integer)
        Dim L As ObjektLandschaft = Wegsuchsystem.getFeldRundrum(Feld.KooX, Feld.KooY, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
        Do Until L Is Nothing
            If Objektverwalter.Spielfeld.Einheiten(L.KooX, L.KooY, Schlachtfeld) Is Nothing Then
                'Leeres Feld
                For I = 0 To Transporter.Ladung.Length - 1
                    'Diese Einheit wurde noch nicht entladen
                    If Not EntladeneTruppen.Contains(I) Then
                        Dim E As ObjektEinheit = Transporter.Ladung(I)
                        If E IsNot Nothing Then
                            'Die Einheit kann darüber laufen.
                            If E.CanMoveOverTile(L.KooX, L.KooY, Schlachtfeld) Then
                                'ein weiteres Entladungsfeld.
                                EFelder += 1
                                EntladeneTruppen.Push(I)
                            End If
                        End If
                    End If
                Next
            End If
            L = Wegsuchsystem.getFeldRundrum(Feld.KooX, Feld.KooY, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
        Loop
        Return EFelder
    End Function

    ''' <summary>
    ''' Verlädt die Truppen in Transporter
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub EinheitenVerladen()
        While MomentaneEinheit < Einheiten.Length
            Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
            If ExistUnit(Einheit) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheit.Ladung.Length = 0 Then
                        'Es ist auch keine Transport Einheit
                        MoveUnitToTransporter(Einheit)
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
    End Sub
    Protected Sub MoveUnitToTransporter(ByVal Einheit As ObjektEinheit)
        Dim AlterModus As KIModiIntern = KIModusIntern
        KIModusIntern = KIModiIntern.TransporterVerladen
        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
        Dim Ziel As Vector3 = GetTransporter(Einheit, WSS)
        'Wir haben einen Transporter gefunden!
        If Ziel.X >= 0 Then
            If Ziel.Z >= 0 Then
                'Wir können ihn erreichen!
                If Ziel.Z = 0 Then
                    'Sogar ihn dieser Runde!
                    Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Fracht, Nothing, WSS, 4)
                    EinheitGezogenVonVorneStarten()
                    Exit Sub
                Else
                    Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                    EinheitGezogenVonVorneStarten()
                    Exit Sub
                End If
            Else
                'Leider ist er noch zu weit weg!
                Einheitauswählen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                EinheitGezogenVonVorneStarten()
                Exit Sub
            End If
        ElseIf Ziel.Z < 0 Or Ziel.Z > 0 Then 'Der Transporter kommt noch vorbei und dann sind wir eh weg!
            'schauen wir mal ob unter uns ein Gebäude ist
            Dim Gebäude As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Einheit.X, Einheit.Y, Schlachtfeld).Gebäude
            If Not Gebäude Is Nothing Then
                If Gebäude.GetBaulisteThisPlayer.Length > 0 And Spieler.Team = Objektverwalter.Spielfeld.Spieler(Gebäude.Spieler).Team Then
                    Dim Ziele As Point() = GetFreeFelder(Einheit, WSS)
                    If Ziele.Length > 0 Then
                        Einheitauswählen(Einheit, Ziele(Zufallszahl(0, Ziele.Length - 1)), KIModiExtern.Warten, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Exit Sub
                    End If
                End If
            End If
        End If
        KIModusIntern = AlterModus
    End Sub
    ''' <summary>
    ''' Findet den nähesten Transporter zu dem wir hin ziehen sollten!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS">Das Wegsuchsystem! Wichtig: komplett ausgebreitet!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporter(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Vector3
        Dim Ziel As New Vector3(-1, -1, -1)
        Dim TransporterWSS As New Stack(Of Wegsuchsystem)
        'so jetzt haben wir alle Transporter!
        For Each Transporter In Einheiten
            'Ist es ein Transporter und können wir ihn benutzen?
            If Not Transporter.IsLowPowerUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                If Transporter.Ladung.Length > 0 Then
                    'Kann er uns Transportieren?
                    If Transporter.IsLoadable(Einheit) Then
                        If Transporter.HasLadung Then
                            'Er hat bereits Ladung
                            If WSS.getRundeDiskret(WSS.getBewegungspunktekosten(Transporter.X, Transporter.Y, Transporter.GetMap), False) = 0 Or Transporter.HatsichBewegt Then
                                'Nur wenn wir ihn jetzt erreichen können nehmen wir ihn als Ziel.
                                'Ansonsten ist er bereits weg!
                                TransporterWSS.Push(New Wegsuchsystem(Transporter, , True))
                            End If
                        Else
                            'Der Transporter sucht sowieso noch Ladung also her damit!
                            TransporterWSS.Push(New Wegsuchsystem(Transporter, , True))
                        End If
                    End If
                End If
            End If
        Next
        'So jetzt haben wir alle Zieltransporter! Dann suchen wir die kürzesten Weg zu den beiden!
        If TransporterWSS.Count > 0 Then
            Dim V As Vector4 = GetMinimaleDauer(TransporterWSS, WSS)

            'Ziel suchen!
            If V.W >= 0 Then
                WSS.Ziel(TransporterWSS(V.W).Einheit.X, TransporterWSS(V.W).Einheit.Y, Schlachtfeld, True, , False)
                If WSS.WegpunkteX.Length > 0 Then
                    If WSS.getRundeDiskret(WSS.getBewegungspunktekosten(WSS.WegpunkteX(0), WSS.WegpunkteY(0), Schlachtfeld), False) = 0 Then
                        'Wir erreichen ihn diese Runde!
                        If TransporterWSS(V.W).Einheit.X = WSS.WegpunkteX(0) And TransporterWSS(V.W).Einheit.Y = WSS.WegpunkteY(0) Then
                            Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), V.Z)
                        Else
                            If TransporterWSS(V.W).Einheit.HatsichBewegt Then
                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            Else
                                Ziel.Z = V.Z
                            End If
                        End If
                    Else
                        'So jetzt sollten wir natürlich nicht auf das Feld treten auf dem der Transporter uns abholen will!
                        If V.X = TransporterWSS(V.W).Einheit.X And V.Y = TransporterWSS(V.W).Einheit.Y Then
                            'Der Transporter ist bereits da dann nichts wie rein!
                            Ziel = New Vector3(V.X, V.Y, -1)
                        Else 'Wir gehen ein Feld vorher hin!
                            'ein neben Feld
                            If WSS.Ziel(V.X, V.Y, False) Then
                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            End If
                        End If
                    End If
                ElseIf V.Z >= 0 Then
                    Ziel.Z = V.Z
                    If V.Z > 0 Or TransporterWSS(V.W).Einheit.HatsichBewegt Then
                        If TransporterWSS(V.W).Einheit.HatsichBewegt Then
                            'Laufen wir mal zu ihm hin!
                            If WSS.Ziel(TransporterWSS(V.W).Einheit.X, TransporterWSS(V.W).Einheit.Y, Schlachtfeld, False, , False) Then

                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            End If
                        Else
                            'So in dieser Runde treffen wir uns nicht
                            If V.X = TransporterWSS(V.W).Einheit.X And V.Y = TransporterWSS(V.W).Einheit.Y Then
                                'Der Transporter ist bereits da dann nichts wie rein!
                                Ziel = New Vector3(V.X, V.Y, V.Z)
                            Else 'Wir gehen ein Feld vorher hin!
                                'ein neben Feld
                                If WSS.Ziel(V.X, V.Y, Schlachtfeld, False, , False) Then

                                    Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt alle Transporter zurück, die in dieser Runde erreicht werden können.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporterDieseRunde(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point()
        Dim Felder As New Stack(Of Point)
        For Each Transporter In Einheiten
            If Transporter.Ladung.Length > 0 Then
                If Transporter.IsLoadable(Einheit) Then
                    If Not Transporter.IsLowPowerUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                        If WSS.getRundeDiskret(WSS.GetBewegungspunktekostenReal(Transporter.X, Transporter.Y, Transporter.GetMap), False) = 0 Then
                            'Wir können ihn in dieser Runde erreichen!
                            Felder.Push(New Point(Transporter.X, Transporter.Y))
                        End If
                    End If
                End If
            End If
        Next
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Sucht die näheste Besetzung und schaut dann ob wir einen Transporter nehmen oder nicht. Wenn wir ziehen geben wir True zurück!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function InfantrieMoveToTransporterOrBesetzung(ByVal Einheit As ObjektEinheit) As Boolean
        Dim AltModus As KIModiIntern = KIModusIntern
        'Wir simulieren, wir würden Truppen verladen
        KIModusIntern = KIModiIntern.TransporterVerladen
        Dim WSS As New Wegsuchsystem(Einheit, , True)
        Dim Zielpunkt As Point = GetNähesteBesetzung(Einheit, WSS)
        'Können wir eine Besetzung über Land erreichen?
        If Zielpunkt.X >= 0 Then
            Dim Dauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(Zielpunkt), False)
            If Dauer >= 2 Then
                Dim Transporter() As Point = GetAllTTPsAndTHelis(GetTransporterDieseRunde(Einheit, WSS))
                If Transporter.Length > 0 Then
                    'Hier sollten wir den besten Transporter aussuchen!
                    Dim BesterTransporter As New Point(-1, -1)
                    Dim MinDauer As Integer = -1
                    For Each T In Transporter
                        Dim Trans As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(T.X, T.Y, Schlachtfeld)
                        Dim TWSS As New Wegsuchsystem(Trans, , True)
                        If TWSS.Ziel(Zielpunkt.X, Zielpunkt.Y, False) Then
                            Dim D2 As Integer = TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Zielpunkt.X, Zielpunkt.Y, Schlachtfeld), False)
                            'Wir kommen zum Ziel
                            If D2 < MinDauer Or MinDauer < 0 Then
                                BesterTransporter = T
                                MinDauer = D2
                            End If
                        End If
                    Next
                    If BesterTransporter.X >= 0 Then
                        'Der Transporter ist der beste!
                        Einheitauswählen(Einheit, BesterTransporter, KIModiExtern.Fracht, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    Else
                        'Wir laufen schon mal los kein Transporter ist ein nützlicher! Seltsam!
                        Einheitauswählen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    End If
                Else
                    'Wir laufen schon mal los!
                    Einheitauswählen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                    EinheitGezogenVonVorneStarten()
                    Return True
                End If
            Else 'wir können so hin laufen!
                Einheitauswählen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                EinheitGezogenVonVorneStarten()
                Return True
            End If
        Else
            KIModusIntern = AltModus
            'Nicht gut! Also per Land geht da rein gar nichts!
            Return False
        End If
        KIModusIntern = AltModus
    End Function
    ''' <summary>
    ''' Gibt aus einem Array von Zieltransportern, die zurück, die TTPs oder T-Helis oder TTLs sind.
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllTTPsAndTHelis(ByVal Transporter() As Point) As Point()
        Dim T As New Stack(Of Point)
        For Each E In Transporter
            If Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "TTP" Or Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "T-HELI" Or Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "TTL" Then
                T.Push(E)
            End If
        Next
        Return T.ToArray
    End Function
#End Region
#Region "Einheiten System"
    Private Class BesetzungsGebäude
        Public X As Integer
        Public Y As Integer
        Public Units As New List(Of Integer)
        Public ListenStelle As Integer
        Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Unit As Integer, ByVal Listenstelle As Integer)
            Units.Add(Unit)
            Me.X = X
            Me.Y = Y
            Me.ListenStelle = Listenstelle
        End Sub
    End Class
    ''' <summary>
    ''' Besetzt Gebäude intelligenter!
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GebäudeBesetzen()
        Dim Besetzungen As New List(Of BesetzungsGebäude)
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
                If Einheit.KannBesetzen = True Then
                    If Einheit.HatsichBewegt = False Then
                        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.GetMovementRange, , Wegsuchsystem.SuchartenEinheiten.EigeneEinheitenIgnorieren)
                        If Einheit.Besetzen = True Then
                            'Diese Einheit besetzt gerade ein Gebäude da macht sie damit gleich weiter
                            Einheitauswählen(Einheit, New Point(Einheit.X, Einheit.Y), KIModiExtern.Besetzen, Nothing, WSS, 4)
                        Else
                            Dim Mov As Integer = Einheit.GetMovementRange
                            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                                    Dim Bew = WSS.getBewegungspunktekosten(X, Y, Einheit.GetMap)
                                    If Bew >= 0 And Bew <= Mov Then
                                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Einheit.GetMap) Is Nothing Or (Einheit.X = X And Einheit.Y = Y) Then
                                            Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, Einheit.GetMap).Gebäude
                                            If G IsNot Nothing Then
                                                If G.GetSpieler.Team <> Spieler.Team Then
                                                    If Besetzungen.Count > 0 Then
                                                        For I = 0 To Besetzungen.Count - 1
                                                            If Besetzungen(I).X = X Then
                                                                If Besetzungen(I).Y = Y Then
                                                                    Besetzungen(I).Units.Add(MomentaneEinheit)
                                                                    Exit For
                                                                End If
                                                            End If
                                                            If I = Besetzungen.Count - 1 Then
                                                                Besetzungen.Add(New BesetzungsGebäude(X, Y, MomentaneEinheit, Besetzungen.Count))
                                                            End If
                                                        Next
                                                    Else
                                                        Besetzungen.Add(New BesetzungsGebäude(X, Y, MomentaneEinheit, 0))
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                Next
                            Next
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        'So jetzt wissen wir welche Einheit welche Gebäude besetzen kann.
        MomentaneEinheit = 0
        Besetzungen.Sort(AddressOf CompareBesetzungen)
        For I = 0 To Besetzungen.Count - 1
            Besetzungen(I).ListenStelle = I
        Next
        Dim NichtGezogen As Boolean = False
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
                If Einheit.KannBesetzen = True Then
                    If Einheit.HatsichBewegt = False Then
                        Dim WSS As Wegsuchsystem = CreateWSS(Einheit)
                        Dim Gebäude As New List(Of BesetzungsGebäude)
                        For I = 0 To Besetzungen.Count - 1
                            If Besetzungen(I).Units.Contains(MomentaneEinheit) Then
                                Gebäude.Add(Besetzungen(I))
                            End If
                        Next
                        If Gebäude.Count > 0 Then
                            If Gebäude(0).Units.Count = 1 Then
                                Capture(Einheit, Gebäude, WSS, Besetzungen)
                            ElseIf (Gebäude(0).Units.Count > 1 And Not Contains1Units(Besetzungen)) Then
                                Capture(Einheit, Gebäude, WSS, Besetzungen)
                            ElseIf Gebäude.Count = 1 Then
                                Capture(Einheit, Gebäude, WSS, Besetzungen)
                            Else
                                NichtGezogen = True
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
            If NichtGezogen Then
                If MomentaneEinheit >= Einheiten.Length Then
                    NichtGezogen = False
                    MomentaneEinheit = 0
                End If
            End If
        End While
        MomentaneEinheit = 0
    End Sub
    Private Shared Function CompareBesetzungen(ByVal x As BesetzungsGebäude, ByVal y As BesetzungsGebäude) As Integer

        If x Is Nothing Then
            If y Is Nothing Then
                ' If x is Nothing and y is Nothing, they're
                ' equal. 
                Return 0
            Else
                ' If x is Nothing and y is not Nothing, y
                ' is greater. 
                Return 1
            End If
        Else
            ' If x is not Nothing...
            '
            If y Is Nothing Then
                ' ...and y is Nothing, x is greater.
                Return -1
            Else
                ' ...and y is not Nothing, compare the 
                ' lengths of the two strings.
                '
                If x.Units.Count < y.Units.Count Then
                    Return -1
                ElseIf x.Units.Count > y.Units.Count Then
                    Return 1
                Else
                    Dim G1 As Integer = Objektverwalter.Spielfeld.Landschaften(x.X, x.Y, Schlachtfeld).Gebäude.GetBauliste.Length
                    Dim G2 As Integer = Objektverwalter.Spielfeld.Landschaften(y.X, y.Y, Schlachtfeld).Gebäude.GetBauliste.Length
                    If G1 > G2 Then
                        Return -1
                    ElseIf G1 < G2 Then
                        Return 1
                    Else
                        Return 0
                    End If
                End If
            End If
        End If

    End Function
    Private Shared Function Contains1Units(ByVal Besetzungen As List(Of BesetzungsGebäude)) As Boolean
        For I = 0 To Besetzungen.Count - 1
            If Besetzungen(I).Units.Count = 1 Then
                Return True
            End If
        Next
        Return False
    End Function
    Private Sub Capture(ByVal Einheit As ObjektEinheit, ByVal Gebäude As List(Of BesetzungsGebäude), ByVal WSS As Wegsuchsystem, ByRef Besetzungen As List(Of BesetzungsGebäude))
        Gebäude.Sort(AddressOf CompareBesetzungen)

        WSS.Ziel(Gebäude(0).X, Gebäude(0).Y, True)
        Dim Bes As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(Gebäude(0).X, Gebäude(0).Y, Schlachtfeld).Gebäude
        If Bes.Angriff = ObjektGebäude.Angriffe.Silo Then
            Dim Ziel2 As Point = GetBestenEinschlagsOrt(Bes.Reichweite, Bes.Schaden)
            Einheitauswählen(Einheit, New Point(Gebäude(0).X, Gebäude(0).Y), KIModiExtern.SiloZünden, New EinheitAmphibienpanzer(0, Ziel2.X, Ziel2.Y), WSS, 4)
        Else
            Einheitauswählen(Einheit, New Point(Gebäude(0).X, Gebäude(0).Y), KIModiExtern.Besetzen, Nothing, WSS, 4)
        End If
        Besetzungen.RemoveAt(Gebäude(0).ListenStelle)
        Dim I As Integer = 0
        While I < Gebäude.Count
            For I2 = 0 To Gebäude(I).Units.Count - 1
                If Gebäude(I).Units(I2) = MomentaneEinheit Then
                    If Gebäude(I).Units.Count = 1 Then
                        Gebäude.RemoveAt(I)
                        I -= 1
                    Else
                        Gebäude(I).Units.RemoveAt(I2)
                    End If
                    Exit For
                End If
            Next
            I += 1
        End While
        For I = 0 To Besetzungen.Count - 1
            Besetzungen(I).ListenStelle = I
        Next
    End Sub
#End Region
#Region "Einheit ziehen und Befehle"
    ''' <summary>
    ''' Führt den momentanen Befehl für die Einheit oder das Gebäude aus
    ''' </summary>
    ''' <param name="Wait">If False Everything is done as fast as possible No Visual Style</param>
    ''' <remarks></remarks>
    Private Sub DoBefehl(ByVal Wait As Boolean)
        Select Case KIModusEinheitenBefehl
            'Hier stehen EinheitenBefehle. Zwei wurden ausgeklammert
            Case KIModiExtern.Warten
                Objektverwalter.Warten()
            Case KIModiExtern.Angriff
                Dim Entfernung As Integer = AktuelleEinheit.GetDistance(Opfer)
                If Entfernung >= AktuelleEinheit.MinimaleReichweite And Entfernung <= AktuelleEinheit.MaximaleReichweite Or Entfernung = 1 And AktuelleEinheit.Waffe1 <> "Keine" Then
                    If TypeOf Me Is KIPassivNetzwerk Then
                        Objektverwalter.Angriff(AktuelleEinheit, Opfer.X, Opfer.Y, AngreiferSchaden, VerteidigerSchaden)
                    Else
                        Objektverwalter.Angriff(AktuelleEinheit, Opfer.X, Opfer.Y)
                    End If
                    If Not Wait Then
                        'We need to Finish this fast!!!
                        Objektverwalter.Spielfeld.Angriff.AngriffEnde()
                        ObjektScript.Prüfen(ObjektScript.Prüfstadien.RundenMitte)
                        Objektverwalter.Spielfeld.Angriff = Nothing
                        Objektverwalter.Spielfeld.Regeln.CheckSieg()
                    End If
                Else
                    Objektverwalter.Warten()
                End If
            Case KIModiExtern.Besetzen
                Objektverwalter.Besetzen()
            Case KIModiExtern.Einen
                Objektverwalter.Einen()
            Case KIModiExtern.Ration
                Objektverwalter.Ration(False, 4, Objektverwalter.Spielfeld.MomentaneSchlacht)
            Case KIModiExtern.Fracht
                Objektverwalter.Fracht()
            Case KIModiExtern.Reparieren
                Objektverwalter.Reparieren(Opfer.X, Opfer.Y)
            Case KIModiExtern.Tarnen
                Objektverwalter.Tarnen()
            Case KIModiExtern.Auftauchen
                Objektverwalter.Auftauchen()
            Case KIModiExtern.Explosion
                Objektverwalter.Explosion()
            Case KIModiExtern.SiloZünden
                Objektverwalter.SiloZünden(Opfer.X, Opfer.Y)
            Case KIModiExtern.Entladen
                If Objektverwalter.Spielfeld.Laufen Is Nothing Then
                    If AktuelleZiel.X = AktuelleEinheit.X And AktuelleZiel.Y = AktuelleEinheit.Y Then
                        Objektverwalter.Entladen(Opfer.X, Opfer.Y, AngreiferSchaden)
                    Else
                        Objektverwalter.Warten()
                    End If
                ElseIf AktuelleZiel.X = Objektverwalter.Spielfeld.Laufen.Position.X And AktuelleZiel.Y = Objektverwalter.Spielfeld.Laufen.Position.Y Then
                    Objektverwalter.Entladen(Opfer.X, Opfer.Y, AngreiferSchaden)
                Else
                    Objektverwalter.Warten()
                End If
            Case KIModiExtern.GebäudeBauen
                Dim ID As String = ObjektLadeklasse.GetGebäudeStringID(AngreiferSchaden)
                Dim M As ObjektSpielMenü = Objektverwalter.Menü
                If ID = "MAUER" Then
                    M.Spielmodus = ObjektSpielMenü.Spielmodi.MauerBauen
                    Objektverwalter.MauerBrückeBauen(Opfer.X, Opfer.Y)
                ElseIf ID = "BRÜCKE" Then
                    M.Spielmodus = ObjektSpielMenü.Spielmodi.BrückeBauen
                    Objektverwalter.MauerBrückeBauen(Opfer.X, Opfer.Y)
                Else
                    Objektverwalter.GebäudeBauen(Opfer.X, Opfer.Y, ID)
                End If

                'ab hier stehen Gebäudebefehle.
            Case KIModiExtern.EinheitBauen
                If Spieler.VeränderteWerte.KeinBau = False Then
                    AnzahldesBauens += 1
                    Objektverwalter.EinheitBauen(New String() {Opfer.EinheitenID, Opfer.Kosten * Spieler.Teurungsrate(Opfer, BauGebäude.Rechteck.X, BauGebäude.Rechteck.Y)}, BauGebäude.Rechteck.X, BauGebäude.Rechteck.Y, True, True)
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                End If
            Case KIModiExtern.FlugzeugträgerBau
                If Spieler.VeränderteWerte.KeinBau = False Then
                    AnzahldesBauens += 1
                    Objektverwalter.EinheitBauenFlugzeugträger(New String() {Opfer.EinheitenID, Opfer.Kosten * Spieler.Teurungsrate(Opfer, BauGebäude.Rechteck.X, BauGebäude.Rechteck.Y)}, BauGebäude.Rechteck.X, BauGebäude.Rechteck.Y, True, True)
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                End If
            Case KIModiExtern.EinheitSchicken
                Objektverwalter.Schicken()
            Case KIModiExtern.Schuss
                BauGebäude.Feuer(Opfer.X, Opfer.Y)
            Case KIModiExtern.OmegaRaketeStarten
                Dim Omega As GebäudeOmega_Rakete = BauGebäude
                Omega.RaketeStarten(Opfer.X, Opfer.Y)
            Case KIModiExtern.FabrikBauen
                Dim Fabrik As GebäudeFabrik = BauGebäude
                Fabrik.Bauen(Opfer.Einheitenname, Opfer.X, Opfer.Y, True)
                If Opfer.X = Fabrik.Rechteck.X Then
                    Fabrik.Variablen(0).Wert -= 2
                ElseIf Opfer.X < Fabrik.Rechteck.X Then
                    Fabrik.Variablen(0).Wert -= 1
                Else
                    Fabrik.Variablen(0).Wert -= 4
                End If
                Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
            Case KIModiExtern.OmegaUpgradeKaufen
                Dim Omega As GebäudeOmega_Rakete = BauGebäude
                Omega.ErweiterungKaufen(Omega.Variablen(Opfer.X).Name)
                Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
            Case KIModiExtern.TemporäreBasisbauen
                Objektverwalter.BuildTempBase()
            Case KIModiExtern.Leuchtrakete
                Objektverwalter.LechtraketeAbfeuern(Opfer.X, Opfer.Y)
            Case KIModiExtern.CreateKOEinheit
                Objektverwalter.CreateKOEinheit()
        End Select
        KIModusEinheitenBefehl = KIModiExtern.Keiner
        If Wait Then KIWarten(2)
        If Not KIModusEinheitenBefehl = KIModiExtern.EinheitBauen And Not KIModusEinheitenBefehl = KIModiExtern.FabrikBauen Then
            MomentaneEinheit -= 1
        End If
        If MomentaneEinheit < 0 Then MomentaneEinheit = 0

        ObjektMaus.Visible = False
        Objektverwalter.Spielfeld.EingabenErlauben = False
        CreateSicht()
    End Sub
    Protected Sub EinheitAbwählen()
        Objektverwalter.Einheitabwählen(True)
        AktuelleEinheit = Nothing
        AktuelleZiel = New Point
        Opfer = Nothing
        KIModusEinheitenBefehl = KIModiExtern.Keiner
    End Sub
    ''' <summary>
    ''' Führt einen Befehl für eine Einheit aus
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Ziel"></param>
    ''' <param name="Aktion"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub Einheitauswählen(ByVal Einheit As ObjektEinheit, ByVal Ziel As Point, ByVal Aktion As KIModiExtern, ByVal Gegner As ObjektEinheit, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        If Not Einheit Is Nothing Then
            Objektverwalter.ZuFeldgehen(Einheit.X, Einheit.Y)
            Dim Spielmenü As ObjektSpielMenü = Objektverwalter.Menü
            AktuelleEinheit = Einheit
            AktuelleZiel = Ziel
            KIModusEinheitenBefehl = Aktion
            Opfer = Gegner
            If Ziel.X <> Einheit.X Or Ziel.Y <> Einheit.Y Then
                If Not WSS Is Nothing Then
                    If WSS.WegpunkteX.Length = 0 Then
                        WSS.Ziel(Ziel.X, Ziel.Y, True)
                    End If
                End If
            End If
            Objektverwalter.Einheitauswählen(AktuelleEinheit.X, AktuelleEinheit.Y, WSS)
            If Not WSS Is Nothing Then
                If WSS.WegpunkteX.Length > 1 Then
                    Spielmenü.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
                End If
            End If
            AufBefehlEndeWarten(Aktion, Warten, Wait)
        End If
    End Sub
    ''' <summary>
    ''' Wir haben eine Einheit ausgewählt und wollen mit ihr noch einen weiteren Befehl ausüben.
    ''' </summary>
    ''' <param name="Ziel"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Befehl"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub NächsterBefehl(ByVal Ziel As Point, ByVal Gegner As ObjektEinheit, ByVal Befehl As KIModiExtern, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        Dim Spielmenü As ObjektSpielMenü = Objektverwalter.Menü
        AktuelleZiel = Ziel
        KIModusEinheitenBefehl = Befehl
        Opfer = Gegner
        If Objektverwalter.Spielfeld.Laufen Is Nothing Then
            If Not Befehl = KIModiExtern.Entladen Then
                WSS.Ziel(Ziel.X, Ziel.Y, True)
                Objektverwalter.Spielfeld.Wegsuchsystem = WSS
                Spielmenü.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
            End If
        ElseIf Objektverwalter.Spielfeld.Laufen.Position = Ziel Then
            'Wir müssen uns nicht mehr bewegen
        Else
            If Not Befehl = KIModiExtern.Entladen Then
                WSS.Ziel(Ziel.X, Ziel.Y, True)
                Objektverwalter.Spielfeld.Wegsuchsystem = WSS
                Spielmenü.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
            End If
        End If
        AufBefehlEndeWarten(Befehl, Warten, Wait)
    End Sub
    ''' <summary>
    ''' Führt einen Befehl für ein Gebäude aus.
    ''' </summary>
    ''' <param name="GebäudeBefehl"></param>
    ''' <param name="Gebäude"></param>
    ''' <param name="WarteZeit"></param>
    ''' <param name="ZuBauendeEinheit">Für manche Befehle ist dies nur eine virtuelle Einheit. Von der die Koordinaten benötigt werden.</param>
    ''' <remarks></remarks>
    Protected Sub GebäudeAuswählen(ByVal GebäudeBefehl As KIModiExtern, ByVal Gebäude As ObjektGebäude, ByVal ZuBauendeEinheit As ObjektEinheit, Optional ByVal WarteZeit As Integer = 2, Optional ByVal Wait As Boolean = True)
        BauGebäude = Gebäude
        Opfer = ZuBauendeEinheit

        AufBefehlEndeWarten(GebäudeBefehl, WarteZeit, Wait)
    End Sub
    ''' <summary>
    ''' Führt einen Befehl für eine Einheit aus für die passive KI!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Aktion"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub Einheitauswählen(ByVal Einheit As ObjektEinheit, ByVal WX As Integer(), ByVal WY As Integer(), ByVal Aktion As KIModiExtern, ByVal Gegner As ObjektEinheit, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        If Not Einheit Is Nothing Then
            Objektverwalter.ZuFeldgehen(Einheit.X, Einheit.Y)
            Dim Spielmenü As ObjektSpielMenü = Objektverwalter.Menü
            AktuelleEinheit = Einheit
            AktuelleZiel = New Point(WX(0), WY(0))
            KIModusEinheitenBefehl = Aktion
            Opfer = Gegner
            If Not WSS Is Nothing Then
                WSS.Ziel(AktuelleZiel.X, AktuelleZiel.Y, True)
            End If
            Objektverwalter.Einheitauswählen(AktuelleEinheit.X, AktuelleEinheit.Y, WSS)
            If WSS Is Nothing Then
                'Die passive KI muss erst noch das Ziel festlegen
                Objektverwalter.Spielfeld.Wegsuchsystem.WegpunkteX = WX
                Objektverwalter.Spielfeld.Wegsuchsystem.WegpunkteY = WY
            End If

            Spielmenü.EinheitBewegungsBefehl(AktuelleZiel.X, AktuelleZiel.Y)

            AufBefehlEndeWarten(Aktion, Warten, Wait)
        End If
    End Sub
#End Region
#Region "Gebäude Feuer"
    ''' <summary>
    ''' Intelligen Deffence System developed by Robosturm for Intelligent Base Deffence.
    ''' </summary>
    ''' <remarks></remarks>
    Public Function IDSBuildingUse() As Boolean
        Dim NewUnits As Boolean = False
        While MomentaneEinheit < Gebäude.Length
            Dim MomGebäude As ObjektGebäude = Gebäude(MomentaneEinheit)
            If Not MomGebäude.GetRealGebäudeID = "VERWEIS" Then
                If MomGebäude.Feuerbereit = 0 Then
                    If TypeOf MomGebäude Is GebäudeLaser Then
                        If LaserUse(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeOmega_Rakete Then
                        Dim Omega As GebäudeOmega_Rakete = MomGebäude
                        If Omega.RaketeFeuerbereit = True Then
                            Dim Ziel As Point = GetBestenEinschlagsOrt(Omega.Reichweite, Omega.Schaden)
                            If Ziel.X >= 0 Then
                                GebäudeAuswählen(KIModiExtern.OmegaRaketeStarten, Omega, New EinheitArtillerie(0, Ziel.X, Ziel.Y), 4)
                            End If
                        ElseIf Spieler.Fonds > 30000 Then
                            For I = 0 To Omega.Variablen.Length - 1
                                If Omega.Variablen(I).Wert = 1 Then
                                    'Wir bauen einen Teil der Omega-Rakete
                                    GebäudeAuswählen(KIModiExtern.OmegaUpgradeKaufen, Omega, New EinheitArtillerie(0, I, 0), 4)
                                    Exit For
                                End If
                            Next
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeMonolith Then
                        If CrystallMonolithUse(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeKristall Then
                        If CrystallMonolithUse(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeSchocklaser_N Then
                        If UseDeathRayNorth(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeSchocklaser_W Then
                        If UseDeathRayWest(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeSchocklaser_S Then
                        If UseDeathRaySouth(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebäude Is GebäudeSchocklaser_O Then
                        If UseDeathRayEast(MomGebäude) Then
                            GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    Else 'A Minicanon or something like this!
                        Dim Ziel As Point = GetBestesGebäudeFeuer(MomGebäude)
                        If Ziel.X >= 0 And Ziel.Y >= 0 Then
                            If MomGebäude.Angriff = ObjektGebäude.Angriffe.SchussN Or MomGebäude.Angriff = ObjektGebäude.Angriffe.SchussW Or MomGebäude.Angriff = ObjektGebäude.Angriffe.SchussS Or MomGebäude.Angriff = ObjektGebäude.Angriffe.SchussO Then
                                GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld), 4)
                            Else
                                'Wir müssen erst noch eine virtuelle Einheit erschaffen.=)
                                GebäudeAuswählen(KIModiExtern.Schuss, MomGebäude, New EinheitAmphibienpanzer(0, Ziel.X, Ziel.Y, False), 4)
                            End If
                        End If
                    End If
                ElseIf TypeOf MomGebäude Is GebäudeFabrik Then
                    Dim Y As Integer = MomGebäude.Rechteck.Y + 2
                    Dim X As Integer = MomGebäude.Rechteck.X - 1
                    Dim Unit As ObjektEinheit = GetBestFactoryUnit(MomGebäude)
                    While Unit IsNot Nothing
                        GebäudeAuswählen(KIModiExtern.FabrikBauen, MomGebäude, Unit, 4)
                        Unit = GetBestFactoryUnit(MomGebäude)
                        NewUnits = True
                    End While
                End If
            End If
            MomentaneEinheit += 1
        End While
        Return NewUnits
    End Function
    ''' <summary>
    ''' should we use our new Laser system?
    ''' </summary>
    ''' <param name="Laser"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function LaserUse(ByVal Laser As GebäudeLaser) As Boolean
        Dim FondsDamage As Integer = 0
        For I As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X - I
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach links markieren
        For I2 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X + I2
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach oben markieren
        For I3 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y - I3
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach unten markiern
        For I4 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y + I4
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        If FondsDamage > 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Produces the best Unit for this Factory!!!
    ''' </summary>
    ''' <param name="Factory"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestFactoryUnit(ByVal Factory As GebäudeFabrik) As ObjektEinheit
        Dim Unit As ObjektEinheit = Nothing
        If Factory.Variablen(1).Wert > 0 Then
            If Factory.Variablen(0).Wert > 0 Then
                Dim Tor As Integer = Factory.Variablen(0).Wert
                'Finding the next production Door
                Dim TotalDamage As Int64 = -1
                If Tor >= 4 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, 1, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 4
                End If
                If Tor >= 2 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, 0, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 2
                End If
                If Tor >= 1 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, -1, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 1
                End If
            End If
        End If
        Return Unit
    End Function
    ''' <summary>
    ''' Let's see what can came out here.
    ''' </summary>
    ''' <param name="Factory"></param>
    ''' <param name="Door">-1,0,1</param>
    ''' <param name="TotalDamage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestUnitForDoor(ByVal Factory As GebäudeFabrik, ByVal Door As Integer, ByRef TotalDamage As Int64) As ObjektEinheit
        Dim Units As String() = Factory.GetBauEinheiten(Factory.Rechteck.X + Door, Factory.Rechteck.Y + 2)
        Dim Unit As ObjektEinheit = Nothing
        For I = 0 To Units.Length - 1
            Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Units(I), Factory.Spieler, Factory.Rechteck.X + Door, Factory.Rechteck.Y + 2, False)
            Dim NewDamage As Int64 = KIGenerellerSuperBau.CalculateDamage(E)
            If NewDamage > TotalDamage Or TotalDamage < 0 Then
                Unit = E
                TotalDamage = NewDamage
            End If
        Next
        Return Unit
    End Function
    ''' <summary>
    ''' Oh yeah! Let's use a Monolith or Crystall right now?
    ''' </summary>
    ''' <param name="Gebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CrystallMonolithUse(ByVal Gebäude As ObjektGebäude) As Boolean
        Dim Kreis(,) As Integer = Kreisfunktion(Gebäude.Reichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                If Kreis(X, Y) > 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Gebäude.Rechteck.X - Gebäude.Reichweite + X, Gebäude.Rechteck.Y - Gebäude.Reichweite + Y, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.Spieler = Gebäude.Spieler Then
                            If E.Munition < E.MunitionMax Then
                                If E.Treibstoff < E.SpritMax Then
                                    Return True
                                End If
                            ElseIf E.getKP < 8 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function UseDeathRayNorth(ByVal DeathRay As GebäudeSchocklaser_N) As Boolean
        Dim D As Int64 = 0
        For Y = -DeathRay.Reichweite To -2
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > 10000 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function UseDeathRayWest(ByVal DeathRay As GebäudeSchocklaser_W) As Boolean
        Dim D As Int64 = 0
        For X = -DeathRay.Reichweite To -2
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > 10000 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function UseDeathRayEast(ByVal DeathRay As GebäudeSchocklaser_O) As Boolean
        Dim D As Int64 = 0
        For X = 2 To DeathRay.Reichweite
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > 10000 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function UseDeathRaySouth(ByVal DeathRay As GebäudeSchocklaser_S) As Boolean
        Dim D As Int64 = 0
        For Y = 2 To DeathRay.Reichweite
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > 10000 Then
            Return True
        Else
            Return False
        End If
    End Function
#End Region

End Class




''' <summary>
''' Diese Klasse hält Funktionen für einen Intelligenten Bau einer Armee parat!
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class KIGenerellerSuperBau
    ''' <summary>
    ''' Mit dieser Zahl werden Bauprioritäten multipliziert!
    ''' </summary>
    ''' <remarks></remarks>
    Const InfantrieGewichtung As Integer = 10
    ''' <summary>
    ''' Wie groß ist eine kleine Karte
    ''' </summary>
    ''' <remarks></remarks>
    Const SmallMap As Integer = 225
    ''' <summary>
    ''' Wie groß ist eine Mittlere Karte
    ''' </summary>
    ''' <remarks></remarks>
    Const MediumMap As Integer = 600
    ''' <summary>
    ''' Minimales Einkommen für Bauänderung
    ''' </summary>
    ''' <remarks></remarks>
    Const Einkommen As Integer = 12000
    ''' <summary>
    ''' Wie weit die näheste Luftwaffe weg sein muss damit sich eine Missile lohnt!
    ''' </summary>
    ''' <remarks></remarks>
    Const LuftwaffenAbstand As Integer = 10
    ''' <summary>
    ''' Wenn wir soviel oder weniger verdienen lohnt sich sparen nicht!
    ''' </summary>
    ''' <remarks></remarks>
    Const MinimalesEinkommen As Integer = 4000
    Shared MinimaleInfiZahl As Integer = 5
    Shared NichtsGebaut As Boolean = True
    Shared AusgabeFonds As Integer = 0
    Shared BauModus As BauModi = BauModi.Infantrie
    Shared Gebäude As ObjektGebäude()
    Shared KI As ObjektKI
    Shared BauWichtigKeit As List(Of TruppenSorten)
    <Serializable()> Public Class PrioritätsBau
        Enum Prioritäten
            Off
            Low
            Normal
            High
        End Enum
        Public Air As Prioritäten
        Public Land As Prioritäten
        Public Sea As Prioritäten
        Public Direct As Prioritäten
        Public Indirect As Prioritäten
        Public Transport As Prioritäten
        Public Infantrie As Prioritäten
        Public DurchschnittlicheTruppenKosten As Integer
        Public Ausgabefonds As Integer
        Public AutoGenerated As Boolean
        Public Sub New(ByVal Air As Prioritäten, ByVal Land As Prioritäten, ByVal Sea As Prioritäten, ByVal Direct As Prioritäten, ByVal Indirect As Prioritäten, ByVal Infantrie As Prioritäten, ByVal Transport As Prioritäten, ByVal DurchschnittlicheTruppenKosten As Integer, ByVal Ausgabefonds As Integer, Optional ByVal AutoGenerated As Boolean = False)
            Me.Air = Air
            Me.Land = Land
            Me.Sea = Sea
            Me.Direct = Direct
            Me.Indirect = Indirect
            Me.Infantrie = Infantrie
            Me.Transport = Transport
            Me.DurchschnittlicheTruppenKosten = DurchschnittlicheTruppenKosten
            If Me.DurchschnittlicheTruppenKosten <= 0 Then Me.DurchschnittlicheTruppenKosten = Einkommen
            Me.Ausgabefonds = Ausgabefonds
            If Me.Ausgabefonds <= 0 Then Me.Ausgabefonds = Einkommen
            Me.AutoGenerated = AutoGenerated
        End Sub
        ''' <summary>
        ''' Gibt die Werte wie bei der New Funktion als Integer mit | getrennt zurück
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides Function ToString() As String
            Return CInt(Air).ToString + "|" + CInt(Land).ToString + "|" + CInt(Sea).ToString + "|" + CInt(Direct).ToString + "|" + CInt(Indirect).ToString + "|" + CInt(Infantrie).ToString + "|" + CInt(Transport).ToString + "|" + DurchschnittlicheTruppenKosten.ToString + "|" + Ausgabefonds.ToString
        End Function
    End Class
    ''' <summary>
    ''' Die einzelnen Bau Module zur Frage bei welchem wir sind!
    ''' </summary>
    ''' <remarks></remarks>
    Enum BauModi
        ''' <summary>
        ''' Wir stellen Infis her!
        ''' </summary>
        ''' <remarks></remarks>
        Infantrie
        ''' <summary>
        ''' Wir bauen Waffen gegen die Lufwaffe!
        ''' </summary>
        ''' <remarks></remarks>
        AntiAirUnits
        ''' <summary>
        ''' Stellt TTP's und T-Helis her!
        ''' </summary>
        ''' <remarks></remarks>
        TransporterBauInfis
        ''' <summary>
        ''' Mal sehen ob wir Transporter bauen!
        ''' </summary>
        ''' <remarks></remarks>
        TransporterBau
    End Enum
    Enum TruppenSorten
        Air
        Ground
        Sea
    End Enum

    Shared BauPrioritäten As PrioritätsBau
    ''' <summary>
    ''' Die einzige Möglichkeit diese Klasse anzusprechen.
    ''' Startet einen sofortigen Bau-Zug einer KI!
    ''' Hinweis: Objektverwalter.Spielfeld.KI darf nicht nichts sein!
    ''' </summary>
    ''' <param name="Gebäude1"></param>
    ''' <remarks></remarks>
    Public Shared Sub Bauen(ByVal Gebäude1 As ObjektGebäude(), ByVal Prioritäten As PrioritätsBau)
        'Shared Variablen setzen.
        AusgabeFonds = 0
        BauModus = BauModi.Infantrie
        NichtsGebaut = True
        KI = Objektverwalter.Spielfeld.KI
        BauPrioritäten = Prioritäten
        Gebäude = Gebäude1
        GenerateBauWichtigkeit()
        'Neutral oder Alles
        Dim AllBuildings As Integer = Objektverwalter.Spielfeld.CountBuildings
        'Gebäude feindlichen
        Dim EnemyBuildings As Integer = CountEnemyBuildings()
        Dim EnemyBuildingProzent As Integer = ProzentualeGebäudeVerteilung() - BauPrioritäten.Infantrie * InfantrieGewichtung
        Dim NeutralBuildings As Integer = CountNeutralBuildings()
        'Eigene Gebäude
        Dim OwnBases As Integer = CountOwnBases()
        Dim OwnAirports As Integer = CountOwnAirports()
        Dim OwnPorts As Integer = CountOwnPorts()
        'Einheiten Feindliche
        Dim EnemyAirUnits As Integer = CountEnemyAirUnits()
        Dim IndirectEnemyUnits As Integer = CountIndirectEnemys()
        Dim DirectEnemyUnits As Integer = CountDirectEnemys()
        Dim EnemyGroundUnits As Integer = CountEnemyGroundUnits()
        Dim EnemySeaForce As Integer = CountEnemySeaUnits()
        Dim EnemyUnits As Integer = CountEnemyUnits()
        Dim EnemyCopters As Integer = CountEnemyCopters()
        Dim EnemyAntiAirUnits As Integer = CountEnemyAntiAirUnits()
        'Einheiten Eigene
        Dim AntiAirUnits As Integer = CountAntiAirUnits()
        Dim OwnGroundUnits As Integer = CountGroundUnits()
        Dim OwnSeaUnits As Integer = CountSeaUnits()
        Dim OwnAirUnits As Integer = CountAirUnits()
        Dim Infis As Integer = CountInfanteristen()
        Dim OwnUnits As Integer = CountOwnUnits()
        Dim OwnLanders As Integer = CountAnyUnit("L-BOOT")
        Dim OwnTransportplanes As Integer = CountAnyUnit("T-FLUGZEUG")
        Dim OwnTTPs As Integer = CountAnyUnit("TTP")
        Dim OwnTHelis As Integer = CountAnyUnit("T-HELI")
        Dim OwnIndirectUnits As Integer = CountIndirectUnits()
        Dim OwnDirectUnits As Integer = CountDirectUnits()
        'Noch andere Sachen
        Dim LBootBau As Boolean = IsTransporterBauSinnvoll(Gebäude) 'Landeboote
        Dim MapSize As Integer = Objektverwalter.Spielfeld.GetSpielgröße
        Dim RationTroops As Integer = GetNeededRation()
        'Wenn das False wird dann schauen wir weiter und weiter und weiter.=D

        Dim Income As Integer = Objektverwalter.Spielfeld.KI.Spieler.Einkommen
        Dim FondsNächsteRunde As Integer = Objektverwalter.Spielfeld.KI.Spieler.Fonds
        FondsNächsteRunde += Income - Objektverwalter.Spielfeld.KI.Spieler.GetRepairCosts
        If Objektverwalter.Spielfeld.Runde > 1 Then
            If BauPrioritäten.Ausgabefonds < KI.Spieler.Fonds Then
                AusgabeFonds = KI.Spieler.Fonds 'Wir dürfen alles ausgeben. Hähä!
            Else
                If Income <= MinimalesEinkommen Then
                    AusgabeFonds = KI.Spieler.Fonds 'Wir dürfen alles ausgeben. Hähä!
                ElseIf Income * 2 <= BauPrioritäten.Ausgabefonds Then
                    AusgabeFonds = KI.Spieler.Fonds
                Else
                    'da muss mir wohl etwas Sparsamer sein!
                    AusgabeFonds = FondsNächsteRunde - BauPrioritäten.DurchschnittlicheTruppenKosten
                End If
            End If
        Else
            AusgabeFonds = KI.Spieler.Fonds
        End If


        'So und jetzt noch ein paar Shared Sachen festlegen
        'Minimale Infanteristen Zahl berechnen!
        Select Case BauPrioritäten.Infantrie
            Case PrioritätsBau.Prioritäten.Off
                MinimaleInfiZahl = 1
            Case PrioritätsBau.Prioritäten.Low
                MinimaleInfiZahl = 3
            Case PrioritätsBau.Prioritäten.Normal
                MinimaleInfiZahl = 5
            Case PrioritätsBau.Prioritäten.High
                MinimaleInfiZahl = 7
        End Select
        If NeutralBuildings / AllBuildings < 10 Or EnemyBuildingProzent < 100 Then
            MinimaleInfiZahl -= (3 - BauPrioritäten.Infantrie)
            If Income > Einkommen Then
                MinimaleInfiZahl -= (3 - BauPrioritäten.Infantrie)
            End If
            If MinimaleInfiZahl <= 0 Then MinimaleInfiZahl = 1
        End If

        Gebäude = TrimGebäude(Gebäude)
        Gebäude = SortGebäude(Gebäude, KI.Spieler)

        Dim MomentaneEinheit As Integer = 0
        If KI.Spieler.VeränderteWerte.KeinBau = False Then
            While MomentaneEinheit < Gebäude.Length
Start:
                NichtsGebaut = True
                'unser erste Aufgabe sollte darin bestehen zu schauen ob wir Infanteristen brauchen!
                If BauModus <= BauModi.Infantrie Then
                    If EnemyBuildingProzent < 100 And Infis <= MinimaleInfiZahl Then
                        If BauPlanÄnderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                    ElseIf Infis < MinimaleInfiZahl Then 'Das spricht für eine Infiflut
                        If BauPlanÄnderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                    ElseIf BauPrioritäten.Infantrie = PrioritätsBau.Prioritäten.High Then
                        If MapSize < MediumMap And Infis / OwnUnits < 50 Then '50% sollten dann woll Infis sein!
                            If BauPlanÄnderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                        End If
                    End If
                End If
                'Wir bauen Truppen gegen die Luftwaffe
                If BauModus <= BauModi.AntiAirUnits Then
                    If AntiAirBau(AntiAirUnits, EnemyAirUnits) Then
                        If BauPlanÄnderung(ProduceAntiAirUnit(EnemyAntiAirUnits, AusgabeFonds), AntiAirUnits) Then GoTo Start
                    End If
                End If
                'Jetzt Truppentransporter!
                If BauModus <= BauModi.TransporterBauInfis Then
                    Select Case BauPrioritäten.Transport
                        Case PrioritätsBau.Prioritäten.Low
                            If Objektverwalter.Spielfeld.Runde < 5 And EnemyBuildingProzent > 120 Then
                                If OwnTTPs + OwnTHelis <= 0 Then
                                    If Zufallszahl(1, 100) <= 50 Then
                                        If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    Else
                                        If BauPlanÄnderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                End If
                            End If
                        Case PrioritätsBau.Prioritäten.Normal
                            If MapSize < SmallMap Then
                                If Objektverwalter.Spielfeld.Runde > 5 And EnemyBuildingProzent > 100 Then
                                    If OwnTTPs < 1 Then
                                        If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    End If
                                End If
                            ElseIf Objektverwalter.Spielfeld.Runde < 6 Or EnemyBuildingProzent > 100 Or RationTroops > 3 Then
                                If MapSize < MediumMap Then
                                    If OwnTTPs < 1 Then
                                        If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    ElseIf OwnTHelis < 1 Then
                                        If BauPlanÄnderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                Else
                                    If OwnTTPs < 2 Then
                                        If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    ElseIf OwnTHelis < 1 Then
                                        If BauPlanÄnderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                End If
                            End If
                        Case PrioritätsBau.Prioritäten.High
                            If MapSize < SmallMap Then
                                If OwnTTPs < 1 Then
                                    If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                End If
                            ElseIf MapSize < MediumMap Then
                                If OwnTTPs < 1 Then
                                    If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                ElseIf OwnTHelis < 1 Then
                                    If BauPlanÄnderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                End If
                            Else
                                If RationTroops > 3 And OwnTTPs < 2 Then
                                    If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                Else
                                    If Objektverwalter.Spielfeld.Runde < 6 Or EnemyBuildingProzent > 100 Then
                                        If OwnTTPs < 2 Then
                                            If BauPlanÄnderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                        ElseIf OwnTHelis < 2 Then
                                            If BauPlanÄnderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                        End If
                                    End If
                                End If
                            End If
                        Case PrioritätsBau.Prioritäten.Off 'Also keine TTPs und T-Heli's
                    End Select
                End If
                'So jetzt kümmern wir uns um die Transporter!
                If BauModus <= BauModi.TransporterBau Then
                    If LBootBau Then
                        'Also wir haben auch Truppen zum transportieren!
                        If BauPrioritäten.Sea < BauPrioritäten.Air Then
                            'Wir bauen mehr T-Flugzeuge als L-Boote
                            Select Case BauPrioritäten.Transport
                                Case PrioritätsBau.Prioritäten.Low 'Eins muss reichen!
                                    If OwnTransportplanes + OwnLanders < 1 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritätsBau.Prioritäten.Normal
                                    If OwnTransportplanes + OwnLanders < 2 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritätsBau.Prioritäten.High
                                    If OwnTransportplanes + OwnLanders < 4 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case Else 'Keine Transporter! :(
                            End Select
                        Else
                            'Wir bauen mehr L-Boote als T-Flugzeuge
                            Select Case BauPrioritäten.Transport
                                Case PrioritätsBau.Prioritäten.Low 'Eins muss reichen!
                                    If OwnTransportplanes + OwnLanders < 1 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritätsBau.Prioritäten.Normal
                                    If OwnTransportplanes + OwnLanders < 2 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritätsBau.Prioritäten.High
                                    If OwnTransportplanes + OwnLanders < 4 Then
                                        If BauPlanÄnderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case Else 'Keine Transporter! :(
                            End Select
                        End If
                    End If
                End If
                'So jetzt bauen wir die beste Einheit!
                BauPlanÄnderung(ProduceBestUnit(AusgabeFonds, OwnAirUnits, OwnGroundUnits, OwnSeaUnits, OwnUnits, EnemyAntiAirUnits, OwnDirectUnits, OwnIndirectUnits), 0)

                'Haben wir etwas Gebaut?
                If NichtsGebaut Then
                    MomentaneEinheit = Gebäude.Length + 1 'Damit wären wir dann wohl fertig, wenn es einmal schief geht geht es auch 2 mal schief!
                Else
                    BauModus = BauModi.Infantrie
                    'Weiter Geht es!
                    MomentaneEinheit = 0
                End If
            End While
        End If




        'Alles löschen
        KI = Nothing
        BauPrioritäten = Nothing
        Gebäude = Nothing
    End Sub

#Region "Truppen Bau"
    Private Shared Function BauPlanÄnderung(ByVal Ausgabe As Integer, ByRef TruppenErhöhung As Integer) As Boolean
        AusgabeFonds -= Ausgabe
        If Ausgabe > 0 Then
            TruppenErhöhung += 1
            NichtsGebaut = False
            BauModus = BauModi.Infantrie
        End If
        If NichtsGebaut Then
            BauModus += 1
        End If
        Return Not NichtsGebaut
    End Function
    ''' <summary>
    ''' Stellt einen Infatristen her!
    ''' </summary>
    ''' <param name="Prüffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function InfisBauen(ByRef Prüffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prüffonds < 0 Then
            Prüffonds = KI.Spieler.Fonds
        End If
        Dim MinRunde As Integer = BauPrioritäten.Infantrie + 1
        For I = 0 To Gebäude.Length - 1
            If IsFeldLeer(Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y) Then
                Dim Infis As String() = GetBuildInfis(Gebäude(I), Prüffonds)
                If Infis.Length > 0 Then
                    If ObjektKI.CanMoveAfterBuilding(New EinheitInfanterie(0, 0, 0), Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y) = True Then
                        If Objektverwalter.Spielfeld.Runde <= MinRunde Or Zufallszahl(1, 100) < 70 Then
                            Dim BilligsteTruppe As ObjektEinheit = Nothing
                            For I2 = 0 To Infis.Length - 1
                                Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Infis(I2), KI.Spieler.Spieler, Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y)
                                If BilligsteTruppe Is Nothing Then
                                    BilligsteTruppe = E
                                ElseIf E.Kosten < BilligsteTruppe.Kosten Then
                                    BilligsteTruppe = E
                                ElseIf E.Kosten = BilligsteTruppe.Kosten And Zufallszahl(0, 2) = 0 Then
                                    BilligsteTruppe = E
                                End If
                            Next
                            'Dann mal los ihr Infis
                            Ausgabe = BilligsteTruppe.Kosten * KI.Spieler.Teurungsrate(BilligsteTruppe, BilligsteTruppe.X, BilligsteTruppe.Y)
                            ProduceUnit(Gebäude(I), BilligsteTruppe)
                            Return Ausgabe
                        Else
                            Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Infis(Zufallszahl(0, Infis.Length - 1)), KI.Spieler.Spieler, Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y)
                            Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                            ProduceUnit(Gebäude(I), E)
                            Return Ausgabe
                        End If
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Stellt eine ganz bestimmte Einheit her.
    ''' </summary>
    ''' <param name="Unit">Die EinheitenID die wir bauen wollen!</param>
    ''' <param name="Prüffonds">Wie teuer die Einheit sein darf!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceUnit(ByVal Unit As String, ByVal Prüffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prüffonds < 0 Then
            Prüffonds = KI.Spieler.Fonds
        End If
        For I = 0 To Gebäude.Length - 1
            If IsFeldLeer(Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebäude(I).CanBuildUnit(Unit, Prüffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit, KI.Spieler.Spieler, Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebäude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Stellt eine ganz bestimmte Einheit her oder die andere.
    ''' </summary>
    ''' <param name="Unit1">Die EinheitenID die wir bauen wollen!</param>
    ''' <param name="Prüffonds">Wie teuer die Einheit sein darf!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceUnitOrUnit(ByVal Unit1 As String, ByVal Unit2 As String, ByVal Prüffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prüffonds < 0 Then
            Prüffonds = KI.Spieler.Fonds
        End If
        For I = 0 To Gebäude.Length - 1
            If IsFeldLeer(Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebäude(I).CanBuildUnit(Unit1, Prüffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit1, KI.Spieler.Spieler, Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebäude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        For I = 0 To Gebäude.Length - 1
            If IsFeldLeer(Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebäude(I).CanBuildUnit(Unit2, Prüffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit2, KI.Spieler.Spieler, Gebäude(I).Rechteck.X, Gebäude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebäude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Baut eine Einheit gegen die Luftwaffe!
    ''' </summary>
    ''' <param name="EnemyAntiAirUnits"></param>
    ''' <param name="Prüffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceAntiAirUnit(ByVal EnemyAntiAirUnits As Integer, ByVal Prüffonds As Integer) As Integer
        Dim Geb As ObjektGebäude = Nothing
        Dim Distance As Integer = -1
        Dim Bauliste As ObjektEinheit() = Nothing
        For I = 0 To BauWichtigKeit.Count - 1
            Select Case BauWichtigKeit(I)
                Case TruppenSorten.Ground 'Schauen wir mal was wir bauen sollten!
                    For Each G In Gebäude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetGroundUnits(Prüffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Ground)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
                Case TruppenSorten.Air
                    For Each G In Gebäude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetAirUnits(Prüffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Air)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
                Case TruppenSorten.Sea
                    For Each G In Gebäude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetSeaUnits(Prüffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Sea)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
            End Select
        Next
ProduceUnit:
        Dim Ausgabe As Integer = 0
        If Bauliste IsNot Nothing Then
            Dim Beste As Integer = -1
            Dim Stärke As Integer = -1
            For I = 0 To Bauliste.Length - 1
                If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                    If Bauliste(I).MinimaleReichweite > 1 And Distance <= LuftwaffenAbstand Then
                        'Jetzt eine Fernwaffe wäre sehr schlecht
                    Else
                        Dim NeuStärke As Integer = GetAntiAirDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                        If NeuStärke > Stärke Then
                            Stärke = NeuStärke
                            Beste = I
                        ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                            Stärke = NeuStärke
                            Beste = I
                        End If
                    End If
                End If
            Next
            If Beste >= 0 Then
                Ausgabe = Bauliste(Beste).Kosten * KI.Spieler.Teurungsrate(Bauliste(Beste), Bauliste(Beste).X, Bauliste(Beste).Y)
                ProduceUnit(Geb, Bauliste(Beste))
                Return Ausgabe
            End If
        End If
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Baut eine Einheit
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared Sub ProduceUnit(ByVal G As ObjektGebäude, ByVal E As ObjektEinheit)
        Dim M As ObjektSpielMenü = Objektverwalter.Menü
        If Not M.Spielmodus = ObjektSpielMenü.Spielmodi.KOSprechen Then
            M.Spielmodus = ObjektSpielMenü.Spielmodi.Nichts
        End If
        KI.KIZieht = True
        KI.KIWarteFrames = 4
        Try
            Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
        Catch
        End Try
        Objektverwalter.EinheitBauen(New String() {E.EinheitenID, E.Kosten * KI.Spieler.Teurungsrate(E, G.Rechteck.X, G.Rechteck.Y)}, G.Rechteck.X, G.Rechteck.Y, True, True)
        Objektverwalter.ZuFeldgehen(E.X, E.Y)
    End Sub
    ''' <summary>
    ''' Baut die Beste Einheit für diese Runde!
    ''' </summary>
    ''' <param name="Prüffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceBestUnit(ByVal Prüffonds As Integer, ByVal OwnAirUnits As Integer, ByVal OwnGroundUnits As Integer, ByVal OwnSeaUnits As Integer, ByVal OwnUnits As Integer, ByVal EnemyAntiAirUnits As Integer, ByVal OwnDirectUnits As Integer, ByVal OwnIndirectUnits As Integer) As Integer
        Dim Ausgabe As Integer = 0
        Dim Geb As ObjektGebäude = Nothing
        Dim Bauliste As ObjektEinheit() = Nothing
        Dim GesamtPriorität As Integer = BauPrioritäten.Land + BauPrioritäten.Sea + BauPrioritäten.Air
        For I = 0 To BauWichtigKeit.Count - 1
            Select Case BauWichtigKeit(I)
                Case TruppenSorten.Air
                    If BauPrioritäten.Air > PrioritätsBau.Prioritäten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnAirUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritäten.Air / GesamtPriorität * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            If EnemyAntiAirUnits - OwnGroundUnits / 2 - OwnSeaUnits / 2 - OwnAirUnits / 4 <= 0 Then
                                For Each G In Gebäude
                                    If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                        Dim GB As ObjektEinheit() = G.GetAirUnits(Prüffonds)
                                        If GB.Length > 0 Then
                                            If Bauliste IsNot Nothing Then
                                                If Bauliste.Length > GB.Length Then
                                                    Geb = G
                                                    Bauliste = GB
                                                End If
                                            Else
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        End If
                                    End If
                                Next
                            ElseIf BauPrioritäten.Air = PrioritätsBau.Prioritäten.High And EnemyAntiAirUnits / OwnAirUnits <= 1 And Zufallszahl(1, 100) < 40 Then
                                For Each G In Gebäude
                                    If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                        Dim GB As ObjektEinheit() = G.GetAirUnits(Prüffonds)
                                        If GB.Length > 0 Then
                                            If Bauliste IsNot Nothing Then
                                                If Bauliste.Length > GB.Length Then
                                                    Geb = G
                                                    Bauliste = GB
                                                End If
                                            Else
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        End If
                                    End If
                                Next
                            End If
                        End If
                    End If
                Case TruppenSorten.Ground
                    If BauPrioritäten.Land > PrioritätsBau.Prioritäten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnGroundUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritäten.Land / GesamtPriorität * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            For Each G In Gebäude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetGroundUnits(Prüffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        ElseIf BauPrioritäten.Land = PrioritätsBau.Prioritäten.High And Zufallszahl(1, 100) < 40 Then
                            For Each G In Gebäude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetGroundUnits(Prüffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        End If
                    End If
                Case TruppenSorten.Sea
                    If BauPrioritäten.Sea > PrioritätsBau.Prioritäten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnSeaUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritäten.Sea / GesamtPriorität * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            For Each G In Gebäude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetSeaUnits(Prüffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        ElseIf BauPrioritäten.Sea = PrioritätsBau.Prioritäten.High And Zufallszahl(1, 100) < 40 Then
                            For Each G In Gebäude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetSeaUnits(Prüffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        End If

                    End If
            End Select
            If Bauliste IsNot Nothing Then
                Exit For
            End If
        Next

        If Bauliste IsNot Nothing Then

            Dim Beste As Integer = -1
            Dim Stärke As Integer = -1
            Dim Durchschnittskosten As Integer = 0
            For Each E In Bauliste
                Durchschnittskosten += E.Kosten
            Next
            Durchschnittskosten /= Bauliste.Length
            Dim Abweichung As Integer = Durchschnittskosten - BauPrioritäten.DurchschnittlicheTruppenKosten
            If Abweichung < 0 Then Abweichung *= -1
            Abweichung += Durchschnittskosten / 4
            Dim DirectProz As Integer = 0
            If OwnUnits > 0 Then
                DirectProz = OwnDirectUnits / OwnUnits * 100
            End If
            If BauPrioritäten.Direct <> PrioritätsBau.Prioritäten.Off Then
                For I = 0 To Bauliste.Length - 1
                    If Bauliste(I).MaximaleReichweite > 1 Then
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Stärke < 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke > Stärke Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
                If Beste < 0 Then
                    For I = 0 To Bauliste.Length - 1
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Stärke < 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke > Stärke Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    Next
                End If
            ElseIf BauPrioritäten.Indirect <> PrioritätsBau.Prioritäten.Off Then
                For I = 0 To Bauliste.Length - 1
                    If Bauliste(I).MaximaleReichweite = 1 Then
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Stärke < 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke > Stärke Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
                If Beste < 0 Then
                    For I = 0 To Bauliste.Length - 1
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Stärke < 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke > Stärke Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                        Stärke = NeuStärke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    Next
                End If
            Else
                If OwnDirectUnits <= BauPrioritäten.Direct / (BauPrioritäten.Direct + BauPrioritäten.Indirect) * 100 Then
                    'Nahwaffen bauen.
                    For I = 0 To Bauliste.Length - 1
                        If Bauliste(I).MaximaleReichweite = 1 Then
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Stärke < 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke > Stärke Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                    If Beste < 0 Then
                        For I = 0 To Bauliste.Length - 1
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Stärke < 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke > Stärke Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Else
                    'Fernwaffen bauen.
                    For I = 0 To Bauliste.Length - 1
                        If Bauliste(I).MaximaleReichweite > 1 Then
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Stärke < 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke > Stärke Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                    If Beste < 0 Then
                        For I = 0 To Bauliste.Length - 1
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritäten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritäten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStärke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Stärke < 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke > Stärke Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        ElseIf NeuStärke = Stärke And Zufallszahl(0, 2) = 0 Then
                                            Stärke = NeuStärke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                End If
            End If
            If Beste >= 0 Then
                Ausgabe = Bauliste(Beste).Kosten * KI.Spieler.Teurungsrate(Bauliste(Beste), Bauliste(Beste).X, Bauliste(Beste).Y)
                ProduceUnit(Geb, Bauliste(Beste))
                Return Ausgabe
            Else
                'So trotzdem was bauen
            End If
        End If
        Return Ausgabe
    End Function
#End Region

#Region "Count Units and Buildings and Stuff like that!"
    ''' <summary>
    ''' Zählt die Lufteinheiten, welche Angreifen können.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.IsFlyingUnit Then
                            If E.CanAttack Then
                                If E.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Fernwaffen der Gegner.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountIndirectEnemys() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.IsFlyingUnit Then
                            If E.MaximaleReichweite > 1 Then
                                If E.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zählt die Direktwaffen der Gegner.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountDirectEnemys() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.IsFlyingUnit Then
                            If E.MinimaleReichweite = 1 Or E.Waffe1 <> "Keine" Then
                                If E.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zählt die Fernwaffen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountIndirectUnits() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.MaximaleReichweite > 1 Then
                            If E.Spieler <> Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zählt die Direktwaffen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountDirectUnits() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.MinimaleReichweite = 1 Or E.Waffe1 <> "Keine" Then
                            If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Neutrale Besetzungen es noch gibt!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountNeutralBuildings() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebäude
                    If Not G Is Nothing Then
                        If G.Spieler = 0 Then
                            If G.Besetzung > 0 Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele feindliche Besetzungen es noch gibt!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyBuildings() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebäude
                    If Not G Is Nothing Then
                        If G.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If G.Besetzung > 0 Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der Einheiten die Bomber angreifen können!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAntiAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.IsAttackable(New EinheitBomber(0, X, Y, False), False, False) Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der feindlichen Einheiten die Bomber angreifen können!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyAntiAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If E.IsAttackable(New EinheitBomber(0, X, Y, False), False, False) Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der Bodeneinheiten + Amphibientruppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountGroundUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.IsGroundUnit Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der Seeeinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountSeaUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.IsSeaUnit Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der Lufteinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.IsFlyingUnit Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der feindlichen Bodeneinheiten + Amphibientruppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyGroundUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.GetSpieler.Team = Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If E.IsGroundUnit Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der feindlichen Seeeinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemySeaUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.GetSpieler.Team = Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If E.IsSeaUnit Then
                                If E.CanAttack Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der feindlichen Einheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.GetSpieler.Team = Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            AirTroops += 1
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die Zahl der feindlichen Helikopter
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyCopters() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.GetSpieler.Team = Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If E.Bewegungsart = MovementSorts.Helikopter.tostring Then
                                If Not E.HasNoWeapons Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zählt die eigenen Truppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            AirTroops += 1
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Wie viele Basen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnBases() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebäude
                    If Not G Is Nothing Then
                        If G.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If TypeOf G Is GebäudeBasis Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Flughafen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnAirports() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebäude
                    If Not G Is Nothing Then
                        If G.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If TypeOf G Is GebäudeFlughafen Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Hafen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnPorts() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim G As ObjektGebäude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebäude
                    If Not G Is Nothing Then
                        If G.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                            If TypeOf G Is GebäudeHafen Then
                                IndirectTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Infanteristen die dieser Spieler kontrolliert zurück
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountInfanteristen() As Integer
        Dim Infanteristen As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.KannBesetzen = True Then
                                If E.Leben > 0 Then
                                    Infanteristen += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Infanteristen
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Einheiten von einem bestimmten Typ zurück.
    ''' </summary>
    ''' <param name="EinheitenID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAnyUnit(ByVal EinheitenID As String) As Integer
        Dim Units As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Höhe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Objektverwalter.Spielfeld.KI.Spieler.Spieler Then
                            If E.Leben > 0 Then
                                If EinheitenID = E.EinheitenID Then
                                    Units += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Wie viel Geld jeder Spieler bekommt
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyBuildingsEachPlayer() As List(Of Integer)
        Dim L As New List(Of Integer)
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Spieler > 0 Then
                If S.Team <> KI.Spieler.Team Then
                    L.Add(S.Geldgebäude)
                End If
            End If
        Next
        Return L
    End Function
    ''' <summary>
    ''' Vergleicht unsere Einnahmen mit denen des besten Spielers
    ''' 100%=Gleichstand an Einnahmen!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProzentualeGebäudeVerteilung() As Single
        Dim EigeneGGebäude As Integer = 0
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Team = KI.Spieler.Team Then
                EigeneGGebäude += S.Geldgebäude * S.FondsproStadt
            End If
        Next
        Dim T As New List(Of String)
        Dim F As New List(Of Integer)
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Spieler > 0 Then
                If S.Team <> KI.Spieler.Team Then
                    If T.Contains(S.Team) Then
                        Dim I As Integer = T.LastIndexOf(S.Team)
                        F(I) += S.Geldgebäude * S.FondsproStadt
                    Else
                        F.Add(S.Geldgebäude * S.FondsproStadt)
                        T.Add(S.Team)
                    End If
                End If
            End If
        Next
        F.Sort()
        Return EigeneGGebäude / F(F.Count - 1) * 100
    End Function
    ''' <summary>
    ''' In welcher Reihenfolge wir Boden, See oder Luftwaffen bauen
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared Sub GenerateBauWichtigkeit()
        BauWichtigKeit = New List(Of TruppenSorten)
        If BauPrioritäten.Air < BauPrioritäten.Sea Then
            If BauPrioritäten.Land < BauPrioritäten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
            Else
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
            End If
        ElseIf BauPrioritäten.Air <= BauPrioritäten.Land Then
            If BauPrioritäten.Land < BauPrioritäten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Air)
            Else
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Air)
            End If
        Else
            If BauPrioritäten.Land < BauPrioritäten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
            Else
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
            End If
        End If

    End Sub
#End Region
#Region "Checking Stuff functions giving back true or false or integers. This functions simply rock!"
    ''' <summary>
    ''' Lohnt es sich überhaupt Landeboote zu bauen?
    ''' </summary>
    ''' <param name="Gebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function IsTransporterBauSinnvoll(ByVal Gebäude() As ObjektGebäude) As Boolean
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Unit.Spieler = KI.Spieler.Spieler Then
                    If Unit.CanAttack Then
                        If Not Unit.IsSeaUnit Then
                            If Not Unit.IsFlyingUnit Then
                                Dim WSS As New Wegsuchsystem(Unit, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
                                If WSS.Wegsuchen(True, Unit.KannBesetzen) < 0 Then
                                    Return True
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Entfernt einfach mal die Gebäude die wir nicht brauchen
    ''' </summary>
    ''' <param name="Gebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function TrimGebäude(ByVal Gebäude As ObjektGebäude()) As ObjektGebäude()
        Dim G2 As New Stack(Of ObjektGebäude)
        For I = 0 To Gebäude.Length - 1
            If Gebäude(I).GetBaulisteThisPlayer.Length > 0 Then
                G2.Push(Gebäude(I))
            End If
        Next
        Gebäude = G2.ToArray
        Return Gebäude
    End Function
    Private Shared Function SortGebäude(ByVal G As ObjektGebäude(), ByVal Spieler As ObjektSpieler) As ObjektGebäude()
        Dim Entfernungen(G.Length - 1) As Integer
        For I = 0 To G.Length - 1
            Dim E As ObjektEinheit = Nothing
            If TypeOf G(I) Is GebäudeBasis Then
                E = New EinheitJagdpanzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebäudeFlughafen Then
                E = New EinheitTarnkappenbomber(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebäudeHafen Then
                E = New EinheitTriton(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebäudeLabor Then
                E = New EinheitMech(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebäudeStadt And G(I).GetBaulisteThisPlayer.Length > 0 Then
                E = New EinheitJagdpanzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            End If
            If E Is Nothing Then
                Entfernungen(I) = -1
            Else
                Dim WSS As New Wegsuchsystem(E, E.X, E.Y, Objektverwalter.Spielfeld.MomentaneSchlacht, -1, False)
                Entfernungen(I) = WSS.Wegsuchen(True, False)
            End If
        Next
        Dim G2(G.Length - 1) As ObjektGebäude
        For I = 0 To G2.Length - 1
            Dim MaxMovementRange As Integer = Objektverwalter.Spielfeld.Breite * Objektverwalter.Spielfeld.Höhe
            Dim GebäudeStelle As Integer = 0
            For I2 = 0 To G.Length - I - 1
                If Entfernungen(I2) < MaxMovementRange And Entfernungen(I2) >= 0 Then
                    GebäudeStelle = I2
                    MaxMovementRange = Entfernungen(I2)
                ElseIf Entfernungen(I2) = MaxMovementRange And Entfernungen(I2) >= 0 And Zufallszahl(0, 1) = 0 Then
                    GebäudeStelle = I2
                    MaxMovementRange = Entfernungen(I2)
                End If
            Next
            G2(I) = G(GebäudeStelle)
            Entfernungen(GebäudeStelle) = Entfernungen(Entfernungen.Length - I - 1)
            G(GebäudeStelle) = G(G.Length - I - 1)
        Next
        Return G2
    End Function
    ''' <summary>
    ''' Gibt zurück ob das Feld leer ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer) As Boolean
        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, ObjektKI.Schlachtfeld)) Then
            Return True
        ElseIf Objektverwalter.Spielfeld.Einheiten(X, Y, ObjektKI.Schlachtfeld).Leben <= 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurück welche Infanteristen von diesem Gebäude gebaut werden können.
    ''' </summary>
    ''' <param name="BauGebäude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetBuildInfis(ByVal BauGebäude As ObjektGebäude, ByVal Prüffonds As Integer) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebäude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebäude.CanBuildUnit(BListe(I), Prüffonds) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Wie viele Truppen brauchen neuen Treibstoff!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetNeededRation() As Boolean
        Dim RationsTruppen As Integer = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Unit.Spieler = KI.Spieler.Spieler Then
                    If Unit.Treibstoff / Unit.SpritMax <= KI.MinimalerTreibstoff Then
                        RationsTruppen += 1
                    ElseIf Unit.Munition / Unit.MunitionMax <= KI.MinimaleMunition Then
                        RationsTruppen += 1
                    End If
                End If
            End If
        Next
        Return RationsTruppen
    End Function
    ''' <summary>
    ''' Brauchen wir was gegen Luftwaffe (T-Heli's und T-Flugzeuge zählen nicht!) 
    ''' </summary>
    ''' <param name="AntiAirUnits"></param>
    ''' <param name="EnemyAirUnits"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function AntiAirBau(ByVal AntiAirUnits As Integer, ByVal EnemyAirUnits As Integer) As Boolean
        If EnemyAirUnits > 0 Then 'Sonst brauchen wir das ja wohl kaum!!!
            If AntiAirUnits <= 0 Then
                Return True
            ElseIf EnemyAirUnits / AntiAirUnits >= 0.5# Then 'Diw Teiler sind noch Variabel
                Return True
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Wie lange ein Jäger braucht zur nächsten Lufteinheit
    ''' </summary>
    ''' <param name="G"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetAirDistance(ByVal G As ObjektGebäude, ByVal Truppensorte As TruppenSorten) As Integer
        Dim WSS As Wegsuchsystem
        Select Case Truppensorte
            Case TruppenSorten.Sea
                WSS = New Wegsuchsystem(New EinheitKreuzer(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case TruppenSorten.Air
                WSS = New Wegsuchsystem(New EinheitJäger(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case TruppenSorten.Ground
                WSS = New Wegsuchsystem(New EinheitFlak(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case Else
                WSS = New Wegsuchsystem(New EinheitJäger(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
        End Select
        Return WSS.Wegsuchen(True, False)
    End Function
    ''' <summary>
    ''' Berechnet wie viel Schaden wir allen Feinden zu fügen würden!
    ''' </summary>
    ''' <param name="Attacker"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function CalculateDamage(ByVal Attacker As ObjektEinheit) As Int64
        Dim Stärke As Int64 = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Attacker.IsAttackable(Unit, False, False) Then
                    If Unit.GetSpieler.Team <> Objektverwalter.Spielfeld.KI.Spieler.Team Then
                        If Not Unit.IsFlyingUnit Then
                            Stärke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                        End If
                    End If
                End If
            End If
        Next
        Return Stärke
    End Function
    ''' <summary>
    ''' Wie viel Schaden wir bei einem Gegner ausrichten würden!
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="AX"></param>
    ''' <param name="AY"></param>
    ''' <param name="Verteidiger"></param>
    ''' <param name="VX"></param>
    ''' <param name="VY"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GegnerVerluste(ByVal Angreifer As ObjektEinheit, ByVal AX As Integer, ByVal AY As Integer, ByVal Verteidiger As ObjektEinheit, ByVal VX As Integer, ByVal VY As Integer) As Integer
        Dim ATKLeben As Single = Angreifer.Leben
        Dim DefLeben As Single = Verteidiger.Leben
        Dim GegenSchaden As Integer() = Angreifer.GetDamage(Verteidiger, False, False)
        If GegenSchaden(0) < 0 Then GegenSchaden(1) = 0
        DefLeben -= GegenSchaden(0) * Angreifer.Leben / 100
        If DefLeben < 0 Then DefLeben = 0
        If Not (GegenSchaden(1) = 2 And Angreifer.MaximaleReichweite > 1) Then
            GegenSchaden = Verteidiger.GetDamage(Angreifer, False, False)
            ATKLeben -= GegenSchaden(0) * DefLeben / 100
            If ATKLeben < 0 Then ATKLeben = 0
        End If
        Dim KVerteidiger As Integer = (Verteidiger.Kosten * Verteidiger.GetSpieler.Teurungsrate(Verteidiger, VX, VY)) * ((Verteidiger.Leben - DefLeben) / 100)
        Dim KAngreifer As Integer = (Angreifer.Kosten * Angreifer.GetSpieler.Teurungsrate(Angreifer, AX, AY)) * ((Angreifer.Leben - ATKLeben) / 100)
        Return KVerteidiger * 2 - KAngreifer
    End Function
    ''' <summary>
    ''' Berechnet wie viel Schaden wir allen fliegenden Feinden zu fügen würden!
    ''' </summary>
    ''' <param name="Attacker"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetAntiAirDamage(ByVal Attacker As ObjektEinheit) As Integer
        Dim Stärke As Integer = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Attacker.IsAttackable(Unit, False, False) Then
                    If Unit.IsFlyingUnit Then
                        If KI IsNot Nothing Then
                            If Unit.GetSpieler.Team <> KI.Spieler.Team Then
                                Stärke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                            End If
                        ElseIf Unit.GetSpieler.Team <> Objektverwalter.Spielfeld.AktuellerSpieler.Team Then
                            Stärke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                        End If
                    End If
                End If
            End If
        Next
        Return Stärke
    End Function
#End Region
End Class